1 x Arduino (in my case it was Arduino Mega 2560 rev2)
1 x PCF8574 expander
1 x 4 digit display with common anode (my was FJ-5461BH)
1 x temperature sensor MCP9700AE
8 x 220 Ohm resistors
some connectors
If you want to build your own simple digital thermometer just for fun, this tutorial is for you. All the “ingredients” you can buy on ebay, aliexpress or in your local electronic shop. The temperature sensor can be replaced with other one, but you need to discover how to connect it to the rest (especially check the operating voltage and pins). Different will be also way to calculate temperature basing on the output voltage.
For my sensor MCP9700AE it is:
1 2 3 4 5 6 7 | float getTemp() { float temp = 0.0; temp = analogRead(A0) * 5 / 1024.0; temp = temp - 0.5; temp = temp / 0.01; return temp; } |
Our simple thermometer display the temperature on 7 segment display. There are many displays on the market, but after you bought any you need to ensure how it works (it means: what pins you should use to control digit and which controls the segments).

Why I used the expander? The expander simplified process of communication with display and reduced number of connectors. To control PCF8574 you should use very useful library PCF8574.h (you can download it here and after that you should import the library to your Arduino IDE)

Connect your segments to pins P0-P7 (remember about resistors – red LED should be powered with 2-2.3 V)
A0-A2 to GND
VCC – 5V
GND to GND in your Arduino on somewhere where you have GND
SDA, SCL we will use to control segments, but only one thing we need to do is to connect to good pins on your Arduino (marked SDA, SCL).
Output of the temperature sensor I connected to A0 port.
Below you will find a short YouTube clip and whole code with comments.
P.S. My first digit is damaged – that’s why I used only three digit to show temperature
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | #include <PCF8574.h> #include <Wire.h> PCF8574 expander; int digit1 = 2; //ports on Arduino int digit2 = 3; int digit3 = 4; int digit4 = 5; const int first = 1; const int second = 2; const int third = 3; const int fourth = 4; float mainTemperature = 0.0; // value to show on 7 segment display long interval = 1000; // interval at which to measure temp (milliseconds) long previousMillis = 0; // will store last time temp was updated int segA = 0; int segB = 1; int segC = 2; int segD = 3; int segE = 4; int segF = 5; int segG = 6; int DOT = 7; void setup() { pinMode(digit1, OUTPUT); //configuring ports as outputs (digits) pinMode(digit2, OUTPUT); pinMode(digit3, OUTPUT); pinMode(digit4, OUTPUT); expander.begin(0x38); //choose addressing scheme for PCF8574A expander.pinMode(segA, OUTPUT); //configuring ports as outputs (segments) expander.pinMode(segB, OUTPUT); expander.pinMode(segC, OUTPUT); expander.pinMode(segD, OUTPUT); expander.pinMode(segE, OUTPUT); expander.pinMode(segF, OUTPUT); expander.pinMode(segG, OUTPUT); expander.pinMode(DOT, OUTPUT); } float getTemp() { float temp = 0.0; temp = analogRead(A0) * 5 / 1024.0; temp = temp - 0.5; temp = temp / 0.01; return temp; } // the loop function runs over and over again forever void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > interval) { //updating temperature only after an interval previousMillis = currentMillis; mainTemperature = (mainTemperature + getTemp()) /2 ; } updateDisplay(mainTemperature); } void updateDisplay( float temp) { int intTemp = temp * 10; for ( int i = 2; i <= 4 ; i++) { //first digit is damaged in my display ;/ selectDigit(i); if (i == 3) { lightNumber(intTemp % 10, true ); } else { lightNumber(intTemp % 10, false ); } intTemp = intTemp / 10; delayMicroseconds(10); lightNumber(10, false ); digitalWrite(digit1, LOW); digitalWrite(digit2, LOW); digitalWrite(digit3, LOW); digitalWrite(digit4, LOW); } } void selectDigit( int number) { switch (number) { case first: digitalWrite(digit1, HIGH); digitalWrite(digit2, LOW); digitalWrite(digit3, LOW); digitalWrite(digit4, LOW); break ; case second: digitalWrite(digit1, LOW); digitalWrite(digit2, HIGH); digitalWrite(digit3, LOW); digitalWrite(digit4, LOW); break ; case third: digitalWrite(digit1, LOW); digitalWrite(digit2, LOW); digitalWrite(digit3, HIGH); digitalWrite(digit4, LOW); break ; case fourth: digitalWrite(digit1, LOW); digitalWrite(digit2, LOW); digitalWrite(digit3, LOW); digitalWrite(digit4, HIGH); break ; } } //Given a number, turns on those segments //If number == 10, then turn off number void lightNumber( int numberToDisplay, boolean dot) { #define SEGMENT_ON LOW #define SEGMENT_OFF HIGH if (dot) { expander.digitalWrite(DOT, SEGMENT_ON); } else { expander.digitalWrite(DOT, SEGMENT_OFF); } switch (numberToDisplay) { case 0: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_ON); expander.digitalWrite(segF, SEGMENT_ON); expander.digitalWrite(segG, SEGMENT_OFF); break ; case 1: expander.digitalWrite(segA, SEGMENT_OFF); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_OFF); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_OFF); expander.digitalWrite(segG, SEGMENT_OFF); break ; case 2: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_OFF); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_ON); expander.digitalWrite(segF, SEGMENT_OFF); expander.digitalWrite(segG, SEGMENT_ON); break ; case 3: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_OFF); expander.digitalWrite(segG, SEGMENT_ON); break ; case 4: expander.digitalWrite(segA, SEGMENT_OFF); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_OFF); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_ON); expander.digitalWrite(segG, SEGMENT_ON); break ; case 5: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_OFF); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_ON); expander.digitalWrite(segG, SEGMENT_ON); break ; case 6: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_OFF); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_ON); expander.digitalWrite(segF, SEGMENT_ON); expander.digitalWrite(segG, SEGMENT_ON); break ; case 7: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_OFF); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_OFF); expander.digitalWrite(segG, SEGMENT_OFF); break ; case 8: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_ON); expander.digitalWrite(segF, SEGMENT_ON); expander.digitalWrite(segG, SEGMENT_ON); break ; case 9: expander.digitalWrite(segA, SEGMENT_ON); expander.digitalWrite(segB, SEGMENT_ON); expander.digitalWrite(segC, SEGMENT_ON); expander.digitalWrite(segD, SEGMENT_ON); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_ON); expander.digitalWrite(segG, SEGMENT_ON); break ; case 10: expander.digitalWrite(segA, SEGMENT_OFF); expander.digitalWrite(segB, SEGMENT_OFF); expander.digitalWrite(segC, SEGMENT_OFF); expander.digitalWrite(segD, SEGMENT_OFF); expander.digitalWrite(segE, SEGMENT_OFF); expander.digitalWrite(segF, SEGMENT_OFF); expander.digitalWrite(segG, SEGMENT_OFF); break ; } } |
great job, but the pins SDA, SCL of PCF8574 in which pins are connected to Arduino?
hi franco, look on your arduino and look for sda and scl pins. On my arduino mega it is pin 20 for sda and 21 for scl. Marked pins : http://michalu.eu/owncloud/index.php/s/wM4EINhLg4nau7p
I had to look in the schematic because my arduino uno there are only the pin numbers that are A5 and A4. Another question: What changes do I need to use a display with common cathode?
Is there a circuit diagram available?
Cześć Michał.
Czy w realu tak lekko mruga ten wyświetlacz jak na filmiku? Przy użyciu 74hc595 wychodzi mniej kodu niż pcf. Ogólnie fajnie że się pochwaliłeś projektem. Ostatnio przez pomyłkę kupiłem 5 max7219 – nadaje się do wyświetlaczy, ale ze wspólną katodą. A ja w rupieciach mam pełno starych 7 segmentów z wspólną anodą. I nie wiem co wymyślić, żeby to wykorzystać – 1) albo dać max7219 i połączyć wszystkie piny za pomocą tranzystorów i rezystorów, czy 2) dać 74hc595 i połączyć zgodnie ze sztuką czyli, anody na tranzystorach z rezystorami i rezystory na segmenty, czy 3) kupić pcf8574 i połączyć jak… no właśnie jak, tak samo jak przy 74hc595?
Pozdrawiam.