In this tutorial I cover the following topics
- Introduction
- Microcontroller's pins
- Experiments
- PWM -- Hardware switching
- Application 1: LED
- Application 2: control RGB LED
- Application 3: servo
I explain different type of microcontroller's pins in Different voltage level coexistence part. Please refere to section Type of pins if this topic is new for you or you don't remember this material.
Turn on and turn off LED with low rate (1000ms for each state). Voltage changes from
LOW
level to HIGH
level and back.
Turned off (LOW
voltage level, close to 0V):
Turned on (HIGH
voltage level, close to 5V):
High-speed switching (1ms for each state).
Now voltage is very stable, around 2.2V:
This is in accordance with expectation as 1/(1+1) * 5V = 2.5V. Because as we have seen in Experiment 1
HIGH
voltage is not exactly 5V but 4.5V so 1/2*4.5V=2.25V.
Circuit with two "reference" LEDs: one (most left) always turend off, and second (most right) always on:
High speed switching but with different length of
LOW
and HIGH
state.
HIGH
1ms, LOW
2ms. Expected voltage is: 1/(1+2)*5V = 1.66V. Taking into account that voltage is rather 4.5V than 5V, expected result is: 1/3 * 4/5V = 1.5V:
Now "reverse" proportions and set
HIGH
state to take 2ms while LOW
state take 1ms. For these assumptions you will obtain:2/3 * 4.5V =3.0V:And finally make a test for
HIGH
state taking 1ms and LOW
state taking 9ms: 1/10 *4.5V = 0.45V = 450mV:
This experiment requires you to add potentiometer to use analog signal to control LED brightnes without the need of programming microcontroller again and again.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#define PIN_LED 12 #define VOLTAGE A0 #define DELAY_TIME 1 void setup() { pinMode(PIN_LED, OUTPUT); } void loop() { int brightness = analogRead(VOLTAGE); brightness = (int)(brightness * (35.0 / 1023.0)); digitalWrite(PIN_LED,HIGH); delay(DELAY_TIME); digitalWrite(PIN_LED,LOW); delay(brightness); } |
With the above code you can control brightness but you will see visible and annoying flickering.
From previous experiment you know that for high
brightness
value LED brightness is lower than maximum brightness but with accompany of visible flickering. Particulary this flickering is visible when you substitute 35
for brightness
:
1 2 3 4 5 6 7 8 |
[...] void loop() { digitalWrite(PIN_LED,HIGH); delay(DELAY_TIME); digitalWrite(PIN_LED,LOW); delay(35); } |
In this case the ratio of LOW
to HIGH
state is equall to 1/35 and the total time of one HIGH
-LOW
cycle is equal to 36 (milliseconds).
In this experiment you take flickering code from previous experiment number 4.2 and preserving ratio of
LOW
to HIGH
state which is equall to 1/35 as well as cycle time which is equal to 36 you change (decrease) time unit from milliseconds to microseconds:
1 2 3 4 5 6 7 8 |
[...] void loop() { digitalWrite(PIN_LED,HIGH); delayMicroseconds(DELAY_TIME); digitalWrite(PIN_LED,LOW); delayMicroseconds(35); } |
Now some magic happends. Ratio of LOW
to HIGH
state is the same but because of different time unit flickering is not visible now.
With the following code:
1 2 3 4 5 6 7 8 9 10 11 12 |
[...] void loop() { int brightness = analogRead(VOLTAGE); int vH = brightness; int vL = 1023-brightness; digitalWrite(PIN_LED,HIGH); delayMicroseconds(vH); digitalWrite(PIN_LED,LOW); delayMicroseconds(vL); } |
you get full control of brightness without flickering thanks to using shorter cycles.
The proportion between HIGH
state and LOW
state are important as this decide about (averaged) output voltage. All timings given below have the same proportion:
1 2 3 4 5 6 7 8 9 10 11 |
HIGH = 1000 LOW = 1000 proportion = 1/1 HIGH = 100 LOW = 100 proportion = 1/1 HIGH = 1 LOW = 1 proportion = 1/1 |
but, as you have seen in experiments, output volatage was the most stable in the last case, where total time of one HIGH-LOW
cycle was the shortest.
In consequence, you can say that both proportion and time window (total time of one cycle) is important.
PWM (Pulse Width Modulation)
- 100% duty cycle (always on):
- 50% duty cycle (on half the time):
- 10% duty cycle
Unfortunately Tinkercad seems to have some problems in this simulation (LED state in case 2 and 3 is incorrect).
- 0% duty cycle (LED is off)
- 50% duty cycle (half LED brightness)
- 100% duty cycle (full LED brightness)
PWM is especially useful to control RGB LED to get full range of colours.
You can apply one of the following codes to your RGB LED:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#define PIN_LED_RED 11 #define PIN_LED_GREEN 10 #define PIN_LED_BLUE 9 double percentage = 0.0; void setup() { pinMode(PIN_LED_RED, OUTPUT); pinMode(PIN_LED_GREEN, OUTPUT); pinMode(PIN_LED_BLUE, OUTPUT); } void loop() { percentage = random(0, 100); analogWrite(PIN_LED_RED, (int)((255.0*percentage)/100.0)); percentage = random(0, 100); analogWrite(PIN_LED_GREEN, (int)((255.0*percentage)/100.0)); percentage = random(0, 100); analogWrite(PIN_LED_BLUE, (int)((255.0*percentage)/100.0)); delay(500); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#define PIN_LED_RED 11 #define PIN_LED_GREEN 10 #define PIN_LED_BLUE 9 int r, g, b; void setup() { pinMode(PIN_LED_RED, OUTPUT); pinMode(PIN_LED_GREEN, OUTPUT); pinMode(PIN_LED_BLUE, OUTPUT); } void loop() { for (r=0; r<255; r += 10) { for (g=0; g<255; g += 10) { for (b=0; b<255; b += 10) { analogWrite(PIN_LED_RED, r); analogWrite(PIN_LED_GREEN, g); analogWrite(PIN_LED_BLUE, b); delay(25); } } } } |
Similar approach as for LED can be applied to control servos.
- 0% duty cycle
- 50% duty cycle
- 100% duty cycle