{"id":109,"date":"2021-06-04T23:36:11","date_gmt":"2021-06-04T21:36:11","guid":{"rendered":"https:\/\/bowfinger.de\/blog\/?p=109"},"modified":"2021-06-04T23:36:11","modified_gmt":"2021-06-04T21:36:11","slug":"a-toy-traffic-signal-with-an-arduino-nano","status":"publish","type":"post","link":"https:\/\/bowfinger.de\/blog\/2021\/06\/a-toy-traffic-signal-with-an-arduino-nano\/","title":{"rendered":"A Toy Traffic Signal with an Arduino Nano"},"content":{"rendered":"\n<p>My kid likes traffic lights. So I decided to quickly build one. I started off on a breadboard with a bunch of components:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>3 \u00d7 LEDs (red, amber, green)<\/li><li>3 \u00d7 470&nbsp;\u03a9 Resistors (only had two, so the third are actually 2 1&nbsp;k\u03a9 in parallel)<\/li><li>1 \u00d7 10&nbsp;k\u03a9 Resistor<\/li><li>1 \u00d7 Pushbutton Switch<\/li><li>1 \u00d7 Arduino Nano (actually a clone)<\/li><\/ul>\n\n\n\n<p>The circuitry is relatively simple. All LEDs&#8217; cathodes point to ground (GND) through a 470&nbsp;\u03a9 resistor each to limit current and not blow anything. The anodes are connected individually to the digital port D3 through D5.<\/p>\n\n\n\n<p>The button works such that, if open, it connects digital port D2 via a 10&nbsp;k\u03a9 resistor to the 3.3&nbsp;V output of the Nano. When it closes, it&#8217;s supposed to pull D2 to GND, so it&#8217;s directly connected to it. The resistor serves to limit the current and &#8211; again &#8211; not blow anything.<\/p>\n\n\n\n<p>That&#8217;s it. Now, for example, pulling D3 high (i.e. applying 3.3&nbsp;V) will switch on the red LED. Likewise for D4 on the yellow and D5 on the green LED. Let&#8217;s introduce some human readable names instead of D2 through D5:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">#include &lt;Arduino.h&gt;\n\n#define BUTTON      D2\n#define LED_RED     D3\n#define LED_YELLOW  D4\n#define LED_GREEN   D5<\/code><\/pre>\n\n\n\n<p>In the <kbd>setup()<\/kbd> function, I set the button pin as an input and the LED pins as outputs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">void setup() {\n  pinMode(LED_RED, OUTPUT);\n  pinMode(LED_YELLOW, OUTPUT);\n  pinMode(LED_GREEN, OUTPUT);\n  pinMode(BUTTON, INPUT);\n}<\/code><\/pre>\n\n\n\n<p>To control the traffic light logic, I scribbled a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Moore_machine\">Moore machine<\/a> on a piece of paper, starting with a pedestrian traffic light (only red and green).<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bowfinger.de\/blog\/wp-content\/uploads\/2021\/05\/moore-machine-1-2.svg\" alt=\"\" class=\"wp-image-129\" width=\"600\" height=\"300\"\/><figcaption>Moore machine with two states (red and green), initialised in the red state. Looped arrows indicate idle non-transition.<\/figcaption><\/figure><\/div>\n\n\n\n<p>The machine starts in the red-light state. It remains there, unless the button is pressed. Then, it instantly switches to green (a pedestrian&#8217;s dream) where it remains until the button is pressed again.<\/p>\n\n\n\n<p>This behaviour can be implemented by putting a simple <kbd>switch case<\/kbd> statement in the main <kbd>loop()<\/kbd> and implementing a state variable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">\/\/ States\nenum states{ ST_R,\n             ST_G\n           }\n\nvoid setState(bool red, bool green) {\n  digitalWrite(LED_RED, red ? HIGH : LOW);\n  digitalWrite(LED_GREEN, green ? HIGH : LOW);\n}\n\nvoid setRed() { setState(true, false); }\nvoid setGreen() { setState(false, true); }\n\nvoid loop() {\n  switch(machineState) {\n    case ST_R:\n      \/\/ Serial.write(\"State: Red\");\n      setRed();\n      break;\n    case ST_G:\n      \/\/ Serial.write(\"State: Green\");\n      setGreen();\n      break;\n}<\/code><\/pre>\n\n\n\n<p>Why use this <kbd>enum<\/kbd> thingy, you say? You could just use an int and call your states <kbd>0, 1, 2<\/kbd>, etc., you say? Yes, you could also sign up for the biannual global brainfuck contest.<\/p>\n\n\n\n<p>But, hey, wait, there are no transitions!<\/p>\n\n\n\n<p>Exactly! For that purpose I&#8217;ll use an interrupt.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><img decoding=\"async\" src=\"https:\/\/media.giphy.com\/media\/9VeY7dXlDaCQg\/giphy.gif\" alt=\"\"\/><\/figure>\n\n\n\n<p>Just add one more function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">void ISR_ButtonToggle() {\n  Serial.write(\"BUUUUTTON!\\n\");\n  if(machineState == ST_R) {\n    machineState = ST_G;\n  } else if (machineState == ST_G) {\n    machineState = ST_R;\n  }\n}<\/code><\/pre>\n\n\n\n<p>And don&#8217;t forget to actually bind the interrupt function in <kbd>setup()<\/kbd>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">attachInterrupt(digitalPinToInterrupt(BUTTON), ISR_ButtonToggle, FALLING);<\/code><\/pre>\n\n\n\n<p>Now that&#8217;s a simple and pretty useless traffic light (well, I still like that I can switch it to green at will, this really should be the default pedestrian crossing light!).<\/p>\n\n\n\n<p>But it is easy to extend. You want a yellow state? Add a yellow state <kbd>ST_Y<\/kbd> to your state machine (the <kbd>switch case<\/kbd> statement). Or you want it to show yellow before switching from green to red? Add a yellow-before-red state <kbd>ST_Y_R<\/kbd>. Or you really like to let people wait? Add a wait state. Oh, and of course you can call your states whatever you want.<\/p>\n\n\n\n<p>Here is my full implementation of a non-pedestrian red-yellow-green traffic light as it is stated in the German traffic rules:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>From red to green, with wait periods, go through<ul><li>Red<\/li><li>Red+Yellow (yes, red+yellow, yellow meaning &#8220;get ready&#8221; and red meaning &#8220;not too fast, it&#8217;s still red, Freundchen!&#8221;)<\/li><li>Green<\/li><\/ul><\/li><li>From green to red, with wait periods, go through<ul><li>Green<\/li><li>Yellow (yes, only yellow. The meaning is disputed. Reasonable people say it means &#8220;Prepare to stop, if you can&#8217;t make it in time, it&#8217;s okay.&#8221; while idiots say it means &#8220;STEP ON THE GAS!&#8221;)<\/li><li>Red (This is also sometimes disputed, I won&#8217;t go into this.)<\/li><\/ul><\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">#include &lt;Arduino.h>\n\n#define BAUDRATE      9600\n#define BUTTON        DD2\n#define LED_RED       DD3\n#define LED_YELLOW    DD4\n#define LED_GREEN     DD5\n\n\/\/ Transition delays\n#define BLINK_WAIT        7\n#define DELAY_R_RY        250\n#define DELAY_RY_G        250\n#define DELAY_G_Y         250\n#define DELAY_Y_R         250\n#define DELAY_R_G         250\n#define DELAY_G_R         250\n\n\/\/ States\nenum states{ ST_R,\n             ST_RY,\n             ST_G,\n             ST_Y,\n             WAIT_R_RY,\n             WAIT_RY_G,\n             WAIT_G_Y,\n             WAIT_Y_R,\n             WAIT_G_R,\n             WAIT_R_G };\n\nstates machineState = ST_R;\nbool builtin_led = false;\n\nvoid setState(bool red, bool yellow, bool green) {\n  digitalWrite(LED_RED, red ? HIGH : LOW);\n  digitalWrite(LED_YELLOW, yellow ? HIGH : LOW);\n  digitalWrite(LED_GREEN, green ? HIGH : LOW);\n}\n\nvoid setRed() { setState(true, false, false); }\nvoid setRedYellow() { setState(true, true, false); }\nvoid setYellow() { setState(false, true, false); }\nvoid setGreen() { setState(false, false, true); }\n\nvoid blinkDelay(int delay_ms) {\n  for(int i=0; i&lt;BLINK_WAIT; i++){\n    delay(delay_ms);\n    digitalWrite(LED_BUILTIN, builtin_led);\n    Serial.write(\".\");\n    builtin_led = !builtin_led;\n  }\n  Serial.write(\"\\n\");\n}\n\nvoid ISR_ButtonToggle() {\n  Serial.write(\"BUUUUTTON!\\n\");\n  if(machineState == ST_R) {\n    machineState = WAIT_R_RY;\n  } else if (machineState == ST_G) {\n    machineState = WAIT_G_Y;\n  }\n}\n\nvoid setup() {\n  pinMode(LED_BUILTIN, OUTPUT);\n  pinMode(LED_RED, OUTPUT);\n  pinMode(LED_YELLOW, OUTPUT);\n  pinMode(LED_GREEN, OUTPUT);\n  digitalWrite(LED_BUILTIN, LOW);\n  digitalWrite(LED_RED, LOW);\n  digitalWrite(LED_YELLOW, LOW);\n  digitalWrite(LED_GREEN, LOW);\n  pinMode(BUTTON, INPUT);\n\n  attachInterrupt(digitalPinToInterrupt(BUTTON), ISR_ButtonToggle, FALLING);\n\n  Serial.begin(BAUDRATE);\n  Serial.write(\"Ready.\\n\");\n}\n\nvoid loop() {\n  switch(machineState) {\n    case ST_R:\n      \/\/ Serial.write(\"State: Red\");\n      setRed();\n      break;\n    case ST_G:\n      \/\/ Serial.write(\"State: Green\");\n      setGreen();\n      break;\n    case WAIT_R_RY:\n      Serial.write(\"Wait: Red->RedYellow\\n\");\n      blinkDelay(DELAY_R_RY);\n      machineState = ST_RY;\n      break;\n    case ST_RY:\n      setRedYellow();\n      machineState = WAIT_RY_G;\n      break;\n    case WAIT_RY_G:\n      Serial.write(\"Wait: RedYellow->Green\\n\");\n      blinkDelay(DELAY_RY_G);\n      machineState = ST_G;\n      break;\n    case WAIT_G_Y:\n      Serial.write(\"Wait: Green->Yellow\\n\");\n      blinkDelay(DELAY_G_Y);\n      machineState = ST_Y;\n      break;\n    case ST_Y:\n      setYellow();\n      machineState = WAIT_Y_R;\n      break;\n    case WAIT_Y_R:\n      Serial.write(\"Wait: Yellow->Red\\n\");\n      blinkDelay(DELAY_Y_R);\n      machineState = ST_R;\n      break;\n    case WAIT_R_G:\n      Serial.write(\"Wait: Red->Green\\n\");\n      blinkDelay(DELAY_R_G);\n      machineState = ST_G;\n      break;\n    case WAIT_G_R:\n      Serial.write(\"Wait: Green->Red\");\n      blinkDelay(DELAY_G_R);\n      machineState = ST_R;\n      break;\n    default:\n      Serial.write(\"Woops...\\n\");\n      machineState = ST_R;\n  }\n}<\/code><\/pre>\n\n\n\n<p>Is this the best way to write this? Hell, no! Is it even a good tutorial? You tell me. I think it&#8217;s fairly simple and shows some evenly common concepts:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Using IO pins<\/li><li>Wiring LEDs without burning them or the output pin<\/li><li>Wiring a button*<\/li><li>Using <kbd>#define<\/kbd> statements to make code more readable and lives more easy<\/li><li>Using some abstraction (<kbd>setState(), setRed()<\/kbd>, etc.)<\/li><li>Using a state machine as an extensible concept<\/li><li>Using an interrupt (Why use an interrupt? Because it interrupts your code exactly when the button is pressed. It makes your little circuit very responsive and &#8211; at least in this example &#8211; it is even easier to write.)<\/li><\/ul>\n\n\n\n<p>*) You may encounter a problem that goes by the name &#8220;bouncing&#8221; (or in the beautiful German language &#8220;prellen&#8221;). That&#8217;s when your button press toggles multiple interrupts in a row. Try putting a capacitor in parallel with the resistor, or as a bad software hack, add a 5\u00a0ms delay (<kbd>delay(5);<\/kbd>) to the end of your interrupt function.<\/p>\n\n\n\n<p>Anyways: My girl loves it. Ha! You thought she&#8217;d be a boy because it was a traffic light. Shame on you!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My kid likes traffic lights. So I decided to quickly build one. I started off on a breadboard with a bunch of components: 3 \u00d7 LEDs (red, amber, green) 3 \u00d7 470&nbsp;\u03a9 Resistors (only had two, so the third are actually 2 1&nbsp;k\u03a9 in parallel) 1 \u00d7 10&nbsp;k\u03a9 Resistor 1 \u00d7 Pushbutton Switch 1 \u00d7&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[14,15],"class_list":["post-109","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-arduino","tag-electronics"],"_links":{"self":[{"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/posts\/109","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/comments?post=109"}],"version-history":[{"count":24,"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/posts\/109\/revisions"}],"predecessor-version":[{"id":138,"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/posts\/109\/revisions\/138"}],"wp:attachment":[{"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/media?parent=109"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/categories?post=109"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bowfinger.de\/blog\/wp-json\/wp\/v2\/tags?post=109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}