10. Input Devices
The assignment of this week is to work in a group to probe an input device's analog and digital signals. The individual assignment is to connect a sensor to a microcontroller board that I have designed and take readings.
This week assignment content:
Softwares used:
Datasheets:
Potentiometer connection and programming Resources:
Tilt sensor connection and programming Resources:
MPU6050 connection and programming Resources:
Thermistor “1206” connection and programming Resources:
10.1. Group assignment
For the group assignment, we have to probe an input device's analog and digital signals. Therefore, we have measured the digital signal of an ultrasonic sensor and the analog signal of a temperature sensor. Click here to enter this week group assignment.
10.2. Individual assignment: Measure something
10.2.1. Potentiometer
I have used a Trimmer Potentiometer 10kOhms to create a simple Goniometer using simple components. The potentiometer is a simple knob that provides a variable resistance, which can be read as an analog input to a microcontroller board. For my project, I will use the change in resistence as a measure of knee angle of movement. For accurate readings, calibraton is requried.
Connection:
Potentiometer has three physical pins. The middle pin is connected to the arduino analog input (A0), while the other outer pins are connected to GND and VCC.
By rotating the shaft of the potentiometer towarad the outer pin that connected to VCC, the resistence will change giving a different analog input to the middle pin (maximum reading is 1023). In the same way, by rotating the shaft toward the GND pin, the resistance will change and the analog input will change (minimum reding 0).
Code:
#define ROTARY_ANGLE_SENSOR A0 //Use analog pin A0 for the Rotary Angle Sensor
#define ADC_REF 3.3 //Rreference voltage of ADC is 3.3v
#define FULL_ANGLE 300.0 //Full value of the rotary angle is 300 degrees
void setup()
{
//Start the serial connection
Serial.begin(9600);
}
void loop()
{
//Read the value of the rotary angle sensor in degrees
int degrees = getDegrees();
//Output it to the serial monitor
Serial.print("The angle between the mark and the start position: ");
Serial.println(degrees);
//The delay between readings
delay(500);
}
int getDegrees()
{
//Read the raw sensor value
int sensor_value = analogRead(ROTARY_ANGLE_SENSOR);
//Convert the sensor reading to degrees and return that value
float voltage = (float)sensor_value * ADC_REF / 1023;
float degrees = (voltage * FULL_ANGLE) / ADC_REF;
return degrees;
}
Example of the serial monitor and plotter output:
Video of the operating system:
10.2.2. Tilt sensor
Tilt sensor was used to detect motion. The one I used, has a cylindrical shape with four physical pins. It has a small ball inside it, which be in contact with all four pins when the sensor is upright. When the sensor tilt more than 45 degree to any direction, the output will be OFF.
Connection:
Code:
void setup()
{
//Start the serial connection
Serial.begin(9600);
pinMode(8, INPUT);
}
void loop()
{
if (digitalRead(8) == 0)
{
//Output it to the serial monitor
Serial.println("Tilt detected");
delay(500);
}
else
{
Serial.println("No tilt");
delay(500);
}
}
Video of the operating system:
10.2.3. Inertial Measurement Unit (IMU) - MPU6050
"MPU6050" is an inertial measurement unit (IMU) of six degrees of freedom (6DOF) that combines a 3-axis accelerometer and a 3-axis gyroscope.
Connection:
I have used two of them for my final project to measure the knee angle. To use two MPU6050 simultaneously, I have connected "ADO" pin of one of them to Vcc and the other to GND and called them by their addresses (0x68 and 0x69). Refer to the following image (taken from Daniels Blog) to understand the connection.
I have mounted the first MPU6050 on my microcontoller board "ATtiny84", which is made to be placed on the thigh ((For design and fabrication process, refer to my Final Project >> Circuit design >> Thigh circuit >> 1.3. Third version)) and mounted the second MPU6050 on the other circuit made to be placed on the shank ((For design and fabrication process, refer to my Final Project >> Circuit design >> Shank circuit)). Arduino UNO was used as ISP to program my board. Rx pin of my microcontroller were connected to Rx pin of Arduino UNO to Receive the readings of physical movement of MPU6050 to Arduino IDE serial monitor.
Notes:
- Upload ArduinoISP code to Arduino UNO first, then upload your code using Arduino UNO to your microcontroller board.
- Remove the connection of Rx while uploading the codes.
Code:
/* http://www.youtube.com/c/electronoobs/eng_arduino_tut76.php
* This is an example where we configure te data of the MPU6050
* and read the Acceleration data and print it to the Monitor monitor
* Arduino pin | MPU6050
* 5V | Vcc
* GND | GND
* A4 | SDA
* A5 | SCL
*/
#include <TinyWireM.h>
#include <SoftwareSerial.h>
#ifdef DEBUG
#endif
//Gyro Variables
float elapsedTime, time, timePrev; //Variables for time control
int gyro_error=0; //We use this variable to only calculate once the gyro data error
int gyro_error2=0;
float Gyr_rawX, Gyr_rawY, Gyr_rawZ; //Here we store the raw data read
float Gyr_rawX2, Gyr_rawY2, Gyr_rawZ2;
float Gyro_angle_x, Gyro_angle_y; //Here we store the angle value obtained with Gyro data
float Gyro_angle_x2, Gyro_angle_y2;
float Gyro_raw_error_x, Gyro_raw_error_y; //Here we store the initial gyro data error
float Gyro_raw_error_x2, Gyro_raw_error_y2;
//Acc Variables
int acc_error=0; //We use this variable to only calculate once the Acc data error
int acc_error2=0;
float rad_to_deg = 180/3.141592654; //This value is for pasing from radians to degrees values
float Acc_rawX, Acc_rawY, Acc_rawZ; //Here we store the raw data read
float Acc_rawX2, Acc_rawY2, Acc_rawZ2;
float Acc_angle_x, Acc_angle_y; //Here we store the angle value obtained with Acc data
float Acc_angle_x2, Acc_angle_y2;
float Acc_angle_error_x, Acc_angle_error_y; //Here we store the initial Acc data error
float Acc_angle_error_x2, Acc_angle_error_y2;
float Total_angle_x, Total_angle_y;
float Total_angle_x2, Total_angle_y2;
SoftwareSerial Monitor(PA1, PA0);
void setup() {
TinyWireM.begin(); //begin the wire comunication
TinyWireM.beginTransmission(0x68); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x6B); //make the reset (place a 0 into the 6B register)
TinyWireM.write(0x00);
TinyWireM.endTransmission(true); //end the transmission
//Gyro config
TinyWireM.beginTransmission(0x68); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x1B); //We want to write to the GYRO_CONFIG register (1B hex)
TinyWireM.write(0x10); //Set the register bits as 00010000 (1000dps full scale)
TinyWireM.endTransmission(true); //End the transmission with the gyro
//Acc config
TinyWireM.beginTransmission(0x68); //Start communication with the address found during search.
TinyWireM.write(0x1C); //We want to write to the ACCEL_CONFIG register
TinyWireM.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
TinyWireM.endTransmission(true);
TinyWireM.begin(); //begin the wire comunication
TinyWireM.beginTransmission(0x69); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x6B); //make the reset (place a 0 into the 6B register)
TinyWireM.write(0x00);
TinyWireM.endTransmission(true); //end the transmission
//Gyro config
TinyWireM.beginTransmission(0x69); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x1B); //We want to write to the GYRO_CONFIG register (1B hex)
TinyWireM.write(0x10); //Set the register bits as 00010000 (1000dps full scale)
TinyWireM.endTransmission(true); //End the transmission with the gyro
//Acc config
TinyWireM.beginTransmission(0x69); //Start communication with the address found during search.
TinyWireM.write(0x1C); //We want to write to the ACCEL_CONFIG register
TinyWireM.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
TinyWireM.endTransmission(true);
Monitor.begin(9600); //Remember to set this same baud rate to the serial monitor
time = millis(); //Start counting time in milliseconds
/*Here we calculate the acc data error before we start the loop
* I make the mean of 200 values, that should be enough*/
if(acc_error==0)
{
for(int a=0; a<200; a++)
{
TinyWireM.beginTransmission(0x68);
TinyWireM.write(0x3B); //Ask for the 0x3B register- correspond to AcX
TinyWireM.endTransmission(false);
TinyWireM.requestFrom(0x68,6);
Acc_rawX=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ; //each value needs two registres
Acc_rawY=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
Acc_rawZ=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
/*---X---*/
Acc_angle_error_x = Acc_angle_error_x + ((atan((Acc_rawY)/sqrt(pow((Acc_rawX),2) + pow((Acc_rawZ),2)))*rad_to_deg));
/*---Y---*/
Acc_angle_error_y = Acc_angle_error_y + ((atan(-1*(Acc_rawX)/sqrt(pow((Acc_rawY),2) + pow((Acc_rawZ),2)))*rad_to_deg));
if(a==199)
{
Acc_angle_error_x = Acc_angle_error_x/200;
Acc_angle_error_y = Acc_angle_error_y/200;
acc_error=1;
}
}
}//end of acc error calculation
if(acc_error2==0)
{
for(int b=0; b<200; b++)
{
TinyWireM.beginTransmission(0x69);
TinyWireM.write(0x3B); //Ask for the 0x3B register- correspond to AcX
TinyWireM.endTransmission(false);
TinyWireM.requestFrom(0x69,6);
Acc_rawX2=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ; //each value needs two registres
Acc_rawY2=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
Acc_rawZ2=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
/*---X---*/
Acc_angle_error_x2 = Acc_angle_error_x2 + ((atan((Acc_rawY2)/sqrt(pow((Acc_rawX2),2) + pow((Acc_rawZ2),2)))*rad_to_deg));
/*---Y---*/
Acc_angle_error_y2 = Acc_angle_error_y2 + ((atan(-1*(Acc_rawX2)/sqrt(pow((Acc_rawY2),2) + pow((Acc_rawZ2),2)))*rad_to_deg));
if(b==199)
{
Acc_angle_error_x2 = Acc_angle_error_x2/200;
Acc_angle_error_y2 = Acc_angle_error_y2/200;
acc_error2=1;
}
}
}//end of acc error calculation
/*Here we calculate the gyro data error before we start the loop
* I make the mean of 200 values, that should be enough*/
if(gyro_error==0)
{
for(int i=0; i<200; i++)
{
TinyWireM.beginTransmission(0x68); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x43); //First adress of the Gyro data
TinyWireM.endTransmission(false);
TinyWireM.requestFrom(0x68,4); //We ask for just 4 registers
Gyr_rawX=TinyWireM.read()<<8|TinyWireM.read(); //Once again we shif and sum
Gyr_rawY=TinyWireM.read()<<8|TinyWireM.read();
/*---X---*/
Gyro_raw_error_x = Gyro_raw_error_x + (Gyr_rawX/32.8);
/*---Y---*/
Gyro_raw_error_y = Gyro_raw_error_y + (Gyr_rawY/32.8);
if(i==199)
{
Gyro_raw_error_x = Gyro_raw_error_x/200;
Gyro_raw_error_y = Gyro_raw_error_y/200;
gyro_error=1;
}
}
}//end of gyro error calculation
if(gyro_error2==0)
{
for(int ii=0; ii<200; ii++)
{
TinyWireM.beginTransmission(0x69); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x43); //First adress of the Gyro data
TinyWireM.endTransmission(false);
TinyWireM.requestFrom(0x69,4); //We ask for just 4 registers
Gyr_rawX2=TinyWireM.read()<<8|TinyWireM.read(); //Once again we shif and sum
Gyr_rawY2=TinyWireM.read()<<8|TinyWireM.read();
/*---X---*/
Gyro_raw_error_x2 = Gyro_raw_error_x2 + (Gyr_rawX2/32.8);
/*---Y---*/
Gyro_raw_error_y2 = Gyro_raw_error_y2 + (Gyr_rawY2/32.8);
if(ii==199)
{
Gyro_raw_error_x2 = Gyro_raw_error_x2/200;
Gyro_raw_error_y2 = Gyro_raw_error_y2/200;
gyro_error2=1;
}
}
}//end of gyro error calculation
}//end of setup void
void loop() {
timePrev = time; // the previous time is stored before the actual time read
time = millis(); // actual time read
elapsedTime = (time - timePrev) / 1000; //divide by 1000 in order to obtain seconds
//////////////////////////////////////Gyro read/////////////////////////////////////
TinyWireM.beginTransmission(0x68); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x43); //First adress of the Gyro data
TinyWireM.endTransmission(false);
TinyWireM.requestFrom(0x68,4); //We ask for just 4 registers
Gyr_rawX=TinyWireM.read()<<8|TinyWireM.read(); //Once again we shif and sum
Gyr_rawY=TinyWireM.read()<<8|TinyWireM.read();
/*Now in order to obtain the gyro data in degrees/seconds we have to divide first
the raw value by 32.8 because that's the value that the datasheet gives us for a 1000dps range*/
/*---X---*/
Gyr_rawX = (Gyr_rawX/32.8) - Gyro_raw_error_x;
/*---Y---*/
Gyr_rawY = (Gyr_rawY/32.8) - Gyro_raw_error_y;
/*Now we integrate the raw value in degrees per seconds in order to obtain the angle
* If you multiply degrees/seconds by seconds you obtain degrees */
/*---X---*/
Gyro_angle_x = Gyr_rawX*elapsedTime;
/*---X---*/
Gyro_angle_y = Gyr_rawY*elapsedTime;
TinyWireM.beginTransmission(0x69); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x43); //First adress of the Gyro data
TinyWireM.endTransmission(false);
TinyWireM.requestFrom(0x69,4); //We ask for just 4 registers
Gyr_rawX2=TinyWireM.read()<<8|TinyWireM.read(); //Once again we shif and sum
Gyr_rawY2=TinyWireM.read()<<8|TinyWireM.read();
/*Now in order to obtain the gyro data in degrees/seconds we have to divide first
the raw value by 32.8 because that's the value that the datasheet gives us for a 1000dps range*/
/*---X---*/
Gyr_rawX2 = (Gyr_rawX2/32.8) - Gyro_raw_error_x2;
/*---Y---*/
Gyr_rawY2 = (Gyr_rawY2/32.8) - Gyro_raw_error_y2;
/*Now we integrate the raw value in degrees per seconds in order to obtain the angle
* If you multiply degrees/seconds by seconds you obtain degrees */
/*---X---*/
Gyro_angle_x2 = Gyr_rawX2*elapsedTime;
/*---X---*/
Gyro_angle_y2 = Gyr_rawY2*elapsedTime;
//////////////////////////////////////Acc read/////////////////////////////////////
TinyWireM.beginTransmission(0x68); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x3B); //Ask for the 0x3B register- correspond to AcX
TinyWireM.endTransmission(false); //keep the transmission and next
TinyWireM.requestFrom(0x68,6); //We ask for next 6 registers starting withj the 3B
/*We have asked for the 0x3B register. The IMU will send a brust of register.
* The amount of register to read is specify in the requestFrom function.
* In this case we request 6 registers. Each value of acceleration is made out of
* two 8bits registers, low values and high values. For that we request the 6 of them
* and just make then sum of each pair. For that we shift to the left the high values
* register (<<) and make an or (|) operation to add the low values.
If we read the datasheet, for a range of+-8g, we have to divide the raw values by 4096*/
Acc_rawX=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ; //each value needs two registres
Acc_rawY=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
Acc_rawZ=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
/*Now in order to obtain the Acc angles we use euler formula with acceleration values
after that we substract the error value found before*/
/*---X---*/
Acc_angle_x = (atan((Acc_rawY)/sqrt(pow((Acc_rawX),2) + pow((Acc_rawZ),2)))*rad_to_deg) - Acc_angle_error_x;
/*---Y---*/
Acc_angle_y = (atan(-1*(Acc_rawX)/sqrt(pow((Acc_rawY),2) + pow((Acc_rawZ),2)))*rad_to_deg) - Acc_angle_error_y;
TinyWireM.beginTransmission(0x69); //begin, Send the slave adress (in this case 68)
TinyWireM.write(0x3B); //Ask for the 0x3B register- correspond to AcX
TinyWireM.endTransmission(false); //keep the transmission and next
TinyWireM.requestFrom(0x69,6); //We ask for next 6 registers starting withj the 3B
/*We have asked for the 0x3B register. The IMU will send a brust of register.
* The amount of register to read is specify in the requestFrom function.
* In this case we request 6 registers. Each value of acceleration is made out of
* two 8bits registers, low values and high values. For that we request the 6 of them
* and just make then sum of each pair. For that we shift to the left the high values
* register (<<) and make an or (|) operation to add the low values.
If we read the datasheet, for a range of+-8g, we have to divide the raw values by 4096*/
Acc_rawX2=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ; //each value needs two registres
Acc_rawY2=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
Acc_rawZ2=(TinyWireM.read()<<8|TinyWireM.read())/4096.0 ;
/*Now in order to obtain the Acc angles we use euler formula with acceleration values
after that we substract the error value found before*/
/*---X---*/
Acc_angle_x2 = (atan((Acc_rawY2)/sqrt(pow((Acc_rawX2),2) + pow((Acc_rawZ2),2)))*rad_to_deg) - Acc_angle_error_x2;
/*---Y---*/
Acc_angle_y2 = (atan(-1*(Acc_rawX2)/sqrt(pow((Acc_rawY2),2) + pow((Acc_rawZ2),2)))*rad_to_deg) - Acc_angle_error_y2;
//////////////////////////////////////Total angle and filter/////////////////////////////////////
/*---X axis angle---*/
Total_angle_x = 0.98 *(Total_angle_x + Gyro_angle_x) + 0.02*Acc_angle_x;
Total_angle_x2 = 0.98 *(Total_angle_x2 + Gyro_angle_x2) + 0.02*Acc_angle_x2;
/*---Y axis angle---*/
Total_angle_y = 0.98 *(Total_angle_y + Gyro_angle_y) + 0.02*Acc_angle_y;
Total_angle_y2 = 0.98 *(Total_angle_y2 + Gyro_angle_y2) + 0.02*Acc_angle_y2;
// Monitor.println(Total_angle_x);
// Monitor.println(Total_angle_y);
// Monitor.println(Total_angle_x2);
// Monitor.println(Total_angle_y2);
int knee_angle;
if( Total_angle_x>90 ){
if ( Total_angle_x2>90 ){
knee_angle = 180 - Total_angle_y + Total_angle_y2;
}
else{
knee_angle = 360 - Total_angle_y - Total_angle_y2;
}
}
else{
if ( Total_angle_x2>90 ){
knee_angle = Total_angle_y + Total_angle_y2;
}
else{
knee_angle = 180 + Total_angle_y - Total_angle_y2;
}
}
Monitor.println(knee_angle - 90);
}
Video of the operating system:
10.2.4. Thermistor - 1206
Thermistors are variable resistors that change its resistance based on temperature changes. There are two types of thermistors, which are Negative Temperature Coefficient "NTC" and Positive Temperature Coefficient "PTC". In "NTC" thermistors as temperature increases, resistance decreases. While in "PTC" thermistors as temperature increases, resistance increases. The thermistor I chose to use in this assignment is "1206", which is an "NTC" type.
Basic Connection:
Since IC circuits can't measure the resistance directly, then we need to measure the voltage and use it to calculate the resistance. Voltage divider rule will be used to calculate the resistance from the voltage point between a known resistor and the thermistor.
Where Vout is the measured voltage between the known resistor and the thermistor, Vin is the input voltage "5V", R1 is the known resistor value in ohms, and R2 is the variable resistance of thermistor.
This equation can be rearranged to find the variable resistance of thermistor.
Finally, the Steinhart-Hart equation is used to find the temperature from the resistance.
Circuit Design:
Using the skills I gained from Electronics Design week, I have created a simple PCB using "ATtiny44" micro-controller. I used Eagle software to draw the circuit board.
First step, import components libraries that will be used to design the circuit. I used two libraries, which are:
Then, add all components needed and design the circuit schemtic: Click here to download the schematic design file.
Design the actual board by shifting from schematic to PCB, rearrange components and route the circuit.
Click here to download the PCB design file.
Show circuit traces only and export it as PNG image.
Show circuit frame only and export it as PNG image.
Generate rml file with Mods:
Use Mods to generate the rml files for traces and frame of the circuit. rml file is sent later to the milling machine becasue it can't understand the PNG image.
Fist, import the traces png file to mods. dpi is shown as 500.024, how ever it should be doubled to 1000.048 to resize it correctly.
Select (1/64) to mill traces image.
Set the x,y, and z origins to zero.
Click on Calculate to produce the RML file.
To generate the frame RML file, repeat the steps but consider inverting the png image and setting mill outline to (1/32).
Traces rml: Click here to download the traces rml file.
Frame rml: Click here to download the frame rml file.
Milling:
Send the traces file first to the SRM-20 milling machine and mill it using (1/64) bit. Then, change the milling bit to (1/32) and start milling the outline. You can find more detailed steps about milling in week 5.
Adjust the milling bit to touch the copper sheet surface as shown in the following image:
The following image shows the circuit board after milling the traces:
Circuit board after milling the frame:
Soldering:
I have gathered all the cirucit components used in the design. The following table list them:
P/N | DESC |
---|---|
ATTINY44A-SSU-ND | IC MCU 8BIT 4KB FLASH 14SOIC |
THERMISTOR NTC 10KOHM 3750K 1206 | |
CER RES 20MHZ 15PF SMD | |
LED ORANGE CLEAR 1206 SMD | |
CAP CER 1UF 50V 10% X7R 1206 | |
RES SMD 100 OHM 1% 1/4W 1206 | |
RES SMD 10K OHM 1% 1/4W 1206 | |
RES SMD 100K OHM 1% 1/4W 1206 | |
CONN HEADER SMD 6POS 2.54MM | |
CONN HEASER SMD 2.54MM |
Then I started soldering the components on my circuit board and here is an image of the final result:
Programming:
For programming my circuit, I used Adruino UNO ad programmer. First step to do this is to set Adruino UNO as ISP programmer.
Connect Arduino UNO to laptop USB port through USB cable.
Click on File > Examples > 11.ArduinoISP > ArduinoISP.
Set your Board option to Arduino UNO and choose the correct Port.
Upload the current code. When the code is uploaded, you will get the following message:
Now, Arduino UNO is ready to be used as a programmer for the ATtiny44 board. Connect ATtiny44 board to Arduino UNO through ISP connector.
AVR ISP 6-pins Header layout:
- Arduino Pin 13 ---> SCK
- Arduino Pin 12 ---> MISO
- Arduino Pin 11 ---> MOSI
- Arduino Pin 10 ---> RESET
- Arduino 5V ---> VCC
- Arduino Ground ---> GND
Set your Board option to ATtiny44 and choose the correct Port. If you don't have the ATtiny44 board shown in the boards list, then you should upload its library to the boards manager (follow steps explained in week 9).
Upload the following code, which output the temperature in Celsius to Arduino IDE serial monitor. The output is sent to "PA2" becuase in my ATtiny44 board, thermistor is connected to PA2 (physical pin: 11).
#include "SoftwareSerial.h"
SoftwareSerial Monitor(1, 0);
int Vo;
float R1 = 100000;
float logR2, R2, T;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
int Tc;
void setup()
{
Monitor.begin(9600);
pinMode(0, OUTPUT);
pinMode(1, INPUT);
}
void loop() {
Vo = analogRead(PA2);
R2 = R1 * (1023.0 / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
Tc = T - 273.15;
Monitor.println(Tc);
delay(200);
}
Video of the operating system: