## PT100 conditioning

Today in the laboratory I propose to electronics students in the fifth year of secondary school to experiment with a PT100 resistance thermometer. We want to measure the temperature detected with PT100 in the range between 0 and 100 °C and acquire it with Arduino Uno witch ADC has input dynamics between 0 and 5 V.

We use a transducer like the one in the figure, purchased from RS, an important electronics distributor who has shop near my home. Here I report the technical sheet: Platinum Resistance Temperature Sensors.

Conditioning is based on the use of the resistive Wheatstone bridge and the differential amplifier with LM741 or TL081 opamp. These opamps require dual power supply.
We connect the PT100 in 2-wire connection mode and calculate that for measurements in the range between 0 and 100 °C its resistance varies between 100 Ω and 138.5 Ω. We choose the other resistances of the bridge: two of 1 kΩ and one of 100 Ω which serves as a reference for the measurement of the PT100 at 0 °C. In the diagram we report our conditioning. The VB voltage is set at 450 mV as a measurement reference, while the VA voltage detected on the voltage scores with the PT100 can vary between 450 mV and 610 mV.

Our analysis for the Arduino sketch considers that the resistive variations of the PT100 are in the order of mΩ and consequently also the voltage variations measured on the VAB bridge are small (in the order of mV) while on the contrary the floating point calculations performed by Arduino they are poor in resolution (two decimal places); so we prefer to program the calculations in Arduino working in mV, ie translating VO into mV rather than Volt.

```// PT100 range 0 - 100 °C using
// Wheatstone bridge and differential
// amplifier with LM741

int pt100;
float Vab, Va, Vo, Rpt100, T;

void setup()
{
Serial.begin(9600);
}

void loop()
{
pt100 = analogRead(A0);     // 10 bits code
Vo = pt100/1024.00*5000.00; // voltage in mV
Vab = Vo/31.91;    // amplifier gains: 150k/4.7k=31.91
Va = Vab+454.54;   // bridge reference voltage in mV:
// 5V*100/(1k+100)
Rpt100 = (Va*1000.00)/(5000.00-Va);  // PT100 voltage in mV:
// 5V*Rpt100/(1k+Rpt100)
T = (Rpt100-100)/0.385;  // pt100 transducer relationship:
// Rpt100=100*(1+0.00385*T)
Serial.print("T: ");
Serial.print(T);
Serial.print(char(176));
Serial.println("C");
delay(1000);
}
```

And then also a simulation with Tinkercad where the PT100 is simulated with the series of a 100 Ω resistor and a potentiometer set with a maximum of 38.5 Ω: https://www.tinkercad.com/embed/83ENtZz1e8k (in the Tinkercad window, open the code section and activate the serial monitor before starting the simulation to view the temperatures detected when you turn the potentiometer).

## Simple Simon Game on Arduino

When I was a child, in 1980, I spent some time playing a fun game that asked me to watch, remember and repeat a random sequence proposed from time to time by the microcontroller in a challenge that was inexorably won by the machine! The game was invented in 1978 and was called Simon; today I read his story on Wikipedia: https://en.wikipedia.org/wiki/Simon_(game).The device creates a series of tones and lights and requires a user to repeat the sequence. If the user succeeds, the series becomes progressively longer and more complex. Once the user fails or the time limit runs out, the game is over. Here I propose a simple realization with Arduino uno that you can simulate in https://www.tinkercad.com/things/jKi6DJadMBu or realize in practice with four LEDs and four buttons, plus one for the reset of the game.

Below is the circuit and the sketch made with the students of 3AO Electronics of the school year 2020/21 at IIS Maxwell, Milan.

```/*
V1.0 - Spadaro Filippo 28 may 2021

btnNONE: nessun pulsante premuto
btnGREEN: stampa btnGREEN
btnYELLOW: stampa btnYELLOW
btnRED:   btnRED
btnBLUE: btnBLUE
btnSELECT: stampa SELECT
*/

#define btnGREEN    2
#define btnYELLOW 3
#define btnRED    4
#define btnBLUE     5
#define btnSELECT   1
#define btnNONE     0

#define pinLEDGREEN   2
#define pinLEDYELLOW  3
#define pinLEDRED     4
#define pinLEDBLUE    5

// define the button debounce
int lcd_key = btnNONE;
int lcd_key_precedente = btnNONE;

// game variables
int sequenza[20];
int fineSequenza = 0, i, pulsantePremuto, contaPulsante;
bool indovinaSequenza = false;

// random sequence
void generaSequenza(int inizio, int fine) {
for (i=0; i<20; i++)
{
sequenza[i]=random(inizio,fine+1);
Serial.print(sequenza[i]);
Serial.print(" ");
}
Serial.println();
}

// print sequence
void stampaSequenza(int inizio, int fine) {
for (i=inizio; i<fine; i++) {
digitalWrite(sequenza[i],HIGH);
delay(500);
digitalWrite(sequenza[i],LOW);
delay(500);
}
}

// light only one LED
void illuminaUnLed(int LED1Illuminato, int LED2Spento, int LED3Spento, int LED4Spento)
{
digitalWrite(LED1Illuminato,HIGH);
digitalWrite(LED2Spento,LOW);
digitalWrite(LED3Spento,LOW);
digitalWrite(LED4Spento,LOW);
delay(300);
digitalWrite(LED1Illuminato,LOW);
digitalWrite(LED2Spento,LOW);
digitalWrite(LED3Spento,LOW);
digitalWrite(LED4Spento,LOW);
delay(300);
}

// light all LED
void illuminaTuttiLed(int LED1Illuminato, int LED2Illuminato, int LED3Illuminato, int LED4Illuminato)
{
digitalWrite(LED1Illuminato,HIGH);
digitalWrite(LED2Illuminato,HIGH);
digitalWrite(LED3Illuminato,HIGH);
digitalWrite(LED4Illuminato,HIGH);
delay(300);
digitalWrite(LED1Illuminato,LOW);
digitalWrite(LED2Illuminato,LOW);
digitalWrite(LED3Illuminato,LOW);
digitalWrite(LED4Illuminato,LOW);
delay(300);
}

void giocoDiLuciAccensione(int LED1, int LED2, int LED3, int LED4)
{
digitalWrite(LED1,HIGH);
delay(200);
digitalWrite(LED1,LOW);
digitalWrite(LED2,HIGH);
delay(200);
digitalWrite(LED2,LOW);
digitalWrite(LED3,HIGH);
delay(200);
digitalWrite(LED3,LOW);
digitalWrite(LED4,HIGH);
delay(200);
digitalWrite(LED4,LOW);
delay(200);
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED4,HIGH);
delay(200);
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED4,LOW);
delay(200);
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED4,HIGH);
delay(200);
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED4,LOW);
delay(2000);
}

{
// Serial.println(adc_key_in);     // per il debug
/* Resistori tra 5V e 0V: 2.2k - 1k - 1k - 1k - 2.2k */
if (adc_key_in > 1000) return btnNONE; // 1023 if (adc_key_in < 50) return btnGREEN; // 0 if (adc_key_in < 350) return btnYELLOW; // 320 if (adc_key_in < 500) return btnRED; // 487 if (adc_key_in < 650) return btnBLUE; // 590 if (adc_key_in < 800) return btnSELECT; // 719
return btnNONE;
}

void setup()
{
Serial.begin(9600);
Serial.println("Push start button");   // display "Push the buttons"
pinMode(pinLEDGREEN,OUTPUT);
pinMode(pinLEDYELLOW,OUTPUT);
pinMode(pinLEDRED,OUTPUT);
pinMode(pinLEDBLUE,OUTPUT);
}

void loop()
{
lcd_key = read_LCD_buttons();    // lettura pulsanti
// Serial.println(lcd_key);      // per il debug
if ((lcd_key != btnNONE) && (lcd_key_precedente == btnNONE))    // Anti-rimbalzo
{
// A seconda del pulsante premuto, esegue un'azione
switch (lcd_key)
{
case btnGREEN:
{
illuminaUnLed(pinLEDGREEN, pinLEDYELLOW, pinLEDRED, pinLEDBLUE);
pulsantePremuto= btnGREEN;
delay(200);

if (sequenza[contaPulsante]==pulsantePremuto) {
if (indovinaSequenza==true) {
if (contaPulsante<fineSequenza-1) {
contaPulsante++;
}
else {
fineSequenza++;
stampaSequenza(0, fineSequenza);
contaPulsante = 0;
}
}
else {
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}
}
else {
indovinaSequenza = false;
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}

break;
}
case btnYELLOW:
{
illuminaUnLed(pinLEDYELLOW, pinLEDGREEN, pinLEDRED, pinLEDBLUE);
pulsantePremuto= btnYELLOW;
delay(200);

if (sequenza[contaPulsante]==pulsantePremuto) {
if (indovinaSequenza==true) {
if (contaPulsante<fineSequenza-1) {
contaPulsante++;
}
else {
fineSequenza++;
stampaSequenza(0, fineSequenza);
contaPulsante = 0;
}
}
else {
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}
}
else {
indovinaSequenza = false;
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}

break;
}
case btnRED:
{
illuminaUnLed(pinLEDRED, pinLEDYELLOW, pinLEDGREEN, pinLEDBLUE);
pulsantePremuto= btnRED;
delay(200);

if (sequenza[contaPulsante]==pulsantePremuto) {
if (indovinaSequenza==true) {
if (contaPulsante<fineSequenza-1) {
contaPulsante++;
}
else {
fineSequenza++;
stampaSequenza(0, fineSequenza);
contaPulsante = 0;
}
}
else {
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}
}
else {
indovinaSequenza = false;
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}

break;
}
case btnBLUE:
{
illuminaUnLed(pinLEDBLUE, pinLEDYELLOW, pinLEDGREEN, pinLEDRED);
pulsantePremuto= btnBLUE;
delay(200);

if (sequenza[contaPulsante]==pulsantePremuto) {
if (indovinaSequenza==true) {
if (contaPulsante<fineSequenza-1) {
contaPulsante++;
}
else {
fineSequenza++;
stampaSequenza(0, fineSequenza);
contaPulsante = 0;
}
}
else {
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}
}
else {
indovinaSequenza = false;
illuminaTuttiLed(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);
}

break;
}
case btnSELECT:
{
giocoDiLuciAccensione(pinLEDBLUE, pinLEDRED, pinLEDYELLOW, pinLEDGREEN);

generaSequenza(pinLEDGREEN, pinLEDBLUE);
indovinaSequenza = true;
fineSequenza = 1;
stampaSequenza(0, fineSequenza);
contaPulsante = 0;

break;
}

case btnNONE:
{
// nulla da eseguire
break;
}
}
}
lcd_key_precedente = lcd_key;
delay(50);
}
```

In the realization of the game input, I propose to acquire the signal of the chosen button by using a single analog pin instead of using 5 digital pins, one for each button. In this way I save 5 Arduino digital pins against an alalogic one. The LEDs, on the other hand, are connected to the digital pins. To read the buttons I create a pull-up voltage divider with 5 resistors placed between 5V and 0: 2.2kOhm - 1kOhm - 1kOhm - 1kOhm - 2.2kOhm and acquire the voltage levels with analogRead() which change according to the button that is held down. The function that takes care of this is read_LCD_buttons() which returns the value of the pressed button, and the game is then handled by a switch-case.
A debounce algorithm (managed with the use of the two variables lcd_key and lcd_key_precedente) allows the correct reception of the button chosen by the player: you can see it at the beginning and at the end of the loop().

## Counter 0 - 99 up'n down with 2 display 7 segments

We program an Arduino sketch that creates an up/down counter from 0 to 99 managed by 2 buttons, one for increasing and the other for decreasing, and the system prints the status of the count on 2 seven-segment displays. The circuit is shown in the figure and can also be implemented in practice.
The two buttons are mounted in pull-down with 10kOhm resistors. Arduino accepts a voltage of 5V for the high level and 0V for the low level on the digital pins. The display LEDs are protected with 220Ohm resistors. Arduino generates a voltage of 5V on the digital pins for the high level and supplies a current of about 40mA.

In the sketch below I found a software solution to button bouncing. For information on how to program the debounce of a button you can see my article: https://www.filipposfactory.com/index.php/8-arduino/37-switch-debouncing

Also for information on how to use the Arduino Uno port registers see this article of mine: https://www.filipposfactory.com/index.php/8-arduino/35-counter-0-9-with-7-segments-display-and-arduino-uno or you go to Arduino site: https://www.arduino.cc/en/Reference/PortManipulation.

`int d, u, i=0;`
`// look-up table to encode numbers on display`
`byte numero [10]={B00111111, B00000110, B01011011, B01001111, B01100110,`
`B01101101, B01111101, B00000111, B01111111, B01101111 };`

`// boolean state variables: `
`// 1 = true = HIGH, 0 = false = LOW`
`int upnow=1;`
`int upbefore=1;`
`int downnow=1;`
`int downbefore=1;`

`void setup() {`
`    // pinMode OUTPUT to digital pins from 0 to 7`
`    DDRD = B11111111;`
`    /* pinMode(8,OUTPUT);`
`    pinMode(9,OUTPUT);`
`    pinMode(10,INPUT);`
`    pinMode(11,INPUT);`
`    */`
`    DDRB = B11110011;`
`}`

`void loop() {`
`    // Arduino reads the buttons in polling`
`    upnow=digitalRead (10);`
`    downnow=digitalRead (11);`

`    // up button pressed`
`    if((upnow==HIGH) && (upbefore==0))`
`    {`
`       if (i<99)`
`          i++;`
`    }`
`    upbefore=upnow;`

`    // down button pressed `
`    if((downnow==HIGH) && (downbefore==0))`
`    {`
`       if (i>0)`
`          i--;`
`    }`
`    downbefore=downnow;`

`    // display management: encoding from decimal 0-99 `
`    // to 2 digits for 7 segment displays`
`    d=i/10;`
`    u=i-(d*10);`

`    // print tens`
`    digitalWrite(9,LOW);`
`    digitalWrite(8,HIGH);`
`    PORTD=numero[d];`
`    delay(10);`

`    // print units`
`    digitalWrite(8,LOW);`
`    digitalWrite(9,HIGH);`
`    PORTD= numero[u];`
`    delay(15);`
`}`

The displays are of the common cathode type. The cathode (central pin, above or below) must then be grounded, while to illuminate each of the LEDs it is necessary to supply the relative pin with a positive voltage of about 1.2V. If an impulsive signal is applied to the common cathode, current can be saved by turning on the displays intermittently, but with a frequency such as to make the image appear stable; this technique, called duration modulation
pulse (PWM: Pulse Width Modulation) takes advantage of the properties of the human eye to present a certain persistence of the image on the retina and to possess a lower sensitivity towards impulsive signals.
Thus the respective LEDs of the two displays are connected together and to the same Arduino pin of PORTD (from 0 to 7). Two NPN type BJTs with a 1kOhm resistor connected to the base operate in an ON-OFF configuration. The bases are connected to pins 8 or 9 of the Arduino. When there is 0 voltage in the base, the relative transistor is off, while when I supply 5V, the transistor is on and so the dipslay to which its collector is connected is active.
The sketch is programmed so that to print the tens it sends a HIGH signal to the BJT connected to its cathode, LOW to the other BJT and on the PORTD pins it sends the tens digit; while a few milliseconds later it sends a HIGH signal to the BJT connected to the cathode of the display that displays the units, LOW to the BJT of the tens and on the pins of PORTD it sends the digit of the units; now wait a few milliseconds and this repeats cyclically.

## Switch debouncing

When I use a button the main problem I have to solve in the management via microcontroller is the switch bouncing, when I press it. When a switch mechanism moves from one position to another, it doesn't do so instantly. It takes some time for the mechanism to stabilize in its new position. Meanwhile, the mechanism performs some oscillations such that, if we try to read the state of the switch at that moment, the result will be random.
Arduino (which works at 16 MHz) reads the digital pin to which the button is connected several times within its settling transient and perceives the event as if the button is pressed and released several times.

There are several ways to eliminate the bounce of a switch, both hardware and software. Hardware debouncing involves using an additional circuit to eliminate wobble and receive a smooth, smooth transition from HIGH to LOW or LOW to HIGH. It has the advantage that the process does not occupy the microcontroller, but requires additional components. The other approach is software debouncing. This involves delaying the acceptance of the button press until the transient has passed, in order to be sure that the button has actually been pressed and not an abnormal event.

In the next sketch we look at a software approach. It is a simple process that is based on two states of the button: the previous one, stored in the past iteration of the loop(), and the current one, measured at the beginning of the key press and then the signal transition. If these two values are different, we will accept the button press, otherwise we will not. Furthermore, we must consider that not all switches have the same responses and transients. So, remember that in your projects you will have to adjust a delay() for this (do some testing and find out what is the transition period of your switches).

The sketch that I show you uses three LEDs, each time the button is pressed, one LED lights up and the previous one switches off in a continuous cycle. You can find it to this link: https://www.tinkercad.com/things/3yaJikfCIwn

`// definizioni da usare nel codice`
`#define ledRed 3`
`#define ledYellow 4`
`#define ledGreen 5`
`#define button 7`

`// dichiarazione variabili di stato `
`// e assegnamento valore iniziale`
`int led = 0; `
`int buttonnow = LOW;`
`int buttonbefore= LOW;`

`// setup led e pulsante`
`void setup(){`
`    pinMode(ledRed, OUTPUT); `
`     pinMode(ledYellow, OUTPUT);`
`     pinMode(ledGreen, OUTPUT);`
`     pinMode(button, INPUT); `
`}`

`void loop(){`
`     // polling pulsante con debouncing`
`     buttonnow=digitalRead(button);`
`     if ((buttonnow==HIGH)&&(buttonbefore==LOW)) {`
`         led++;`
`         if (led>3){`
`             led=1;`
`         }`
`     }`
`     buttonbefore=buttonnow;`
`     delay (50); `
`     `

`    // gestione LED `
`     if (led==1){`
`        digitalWrite (ledRed, HIGH); `
`        digitalWrite (ledYellow, LOW); `
`        digitalWrite (ledGreen, LOW);`
`     }`
`     if (led==2){`
`         digitalWrite (ledRed, LOW); `
`         digitalWrite (ledYellow, HIGH); `
`         digitalWrite (ledGreen, LOW);`
`     }`
`     if (led==3){`
`         digitalWrite (ledRed, LOW); `
`         digitalWrite (ledYellow, LOW); `
`         digitalWrite (ledGreen, HIGH);`
`     }`
`}`