#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <EEPROM.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
OneWire ds(6); // Вход датчика 18b20
// AD7793 x16 Umax=73mV CH1_DIFF Fads=4.17Hz
#define SCLK 2
#define CS 3
#define DIN 4
#define DOUT 5
#define AVDD_MONITOR 0b111 // CONF
#define TEMP_SENSOR 0b110 // CONF
#define CH1 0b000 // CONF
#define CH2 0b001 // CONF
#define CH3 0b011 // CONF
#define BIPOLAR 0b00000000 // CONF
#define UNIPOLAR 0b00010000 // CONF
#define GAIN_1 0b000 // CONF
#define GAIN_2 0b001 // CONF
#define GAIN_4 0b010 // CONF
#define GAIN_8 0b011 // CONF
#define GAIN_16 0b100 // CONF
#define GAIN_32 0b101 // CONF
#define GAIN_64 0b110 // CONF
#define GAIN_128 0b111 // CONF
#define F_ADC_500 0b0001 // MODE
#define F_ADC_250 0b0010 // MODE
#define F_ADC_125 0b0011 // MODE
#define F_ADC_62_5 0b0100 // MODE
#define F_ADC_50_0 0b0101 // MODE
#define F_ADC_39_2 0b0110 // MODE
#define F_ADC_33_3 0b0111 // MODE
#define F_ADC_19_6 0b1000 // MODE
#define F_ADC_16_7 0b1001 // MODE
#define F_ADC_12_5 0b1011 // MODE
#define F_ADC_10_0 0b1100 // MODE
#define F_ADC_8_33 0b1101 // MODE
#define F_ADC_6_25 0b1110 // MODE
#define F_ADC_4_17 0b1111 // MODE
// XA K
const float a[] = {0, 2.5173462 * 10, -1.1662878, -1.08336338, -8.9773540 / 10, -3.7342377 / 10, -8.6632643 / 100, -1.0450598 / 100, -5.1920577 / 10000};
const float a1[] = {0, 2.508355 * 10, 7.860106 / 100, -2.503131 / 10, 8.315270 / 100, -1.228034 / 100, 9.804036 / 10000, -4.413030 / 100000, 1.057734 / 1000000, -1.052755 * pow(10, -8)};
const float a2[] = {-1.318058 * 100, 4.830222 * 10, -1.646031, 5.464731 / 100, -9.6550715 / 10000, 8.802193 / 1000000, -3.110810 / 100000000};
// XK L
const float b[] = {1.1573067 / 10000, 1.5884573 * 10, 4.0458554 / 100, 0.3170064, 0.1666128, 5.146958 / 100, 9.5288883 / 1000, 1.0301283 / 1000, 6.0654431 / 100000, 1.5131878 / 1000000};
const float b1[] = {7.2069422 / 1000, 1.5775525 * 10, -0.2261183, 9.4286756 / 1000, -3.5394655 / 10000, 1.0050886 / 100000, -1.9323678 / 10000000, 2.3816891 / 1000000000, -1.7130654 * pow(10, -11), 5.4857331 * pow(10, -14)};
float temp_ds, u, u0, t_iz;
unsigned long times = millis() + 10000;
int menu;
int previousMenu = -1;
bool start = 1;
bool firstBoot = true;
unsigned long previousMillis = 0;
/// калибровка
float gis = 0.2;
float i_1ma = 1.0137;
float r_0_kall = 1.98;
const int analogPin = A0; // Пин, к которому подключен делитель напряжения от аккумулятора
// Данные для делителя напряжения
const float R1 = 46800.0; // 47k
const float R2 = 10250.0; // 10k
const float divider = R2 / (R1 + R2); // Коэффициент передачи
const float Vref = 1.1; // Опорное напряжение
const float batteryVoltageMax = 4.2; // Максимальное напряжение аккумулятора
const float batteryVoltageMin = 3.2; // Минимальное напряжение аккумулятора
void drawBatterySymbol(int batteryLevel) {
int width = map(batteryLevel, 0, 100, 0, 8); // Ширина заполнения аккумулятора
int x = SCREEN_WIDTH - 16; // Правый край дисплея минус ширина аккумулятора
int y = 0; // Верхний край дисплея
// Отрисовка рамки аккумулятора
display.drawRect(x, y, 15, 8, WHITE);
// Отрисовка положительного поляритета аккумулятора
display.drawLine(x - 2, y + 2, x-2, y + 5, WHITE);
// Заполнение аккумулятора
display.fillRect(x + 14 - width, y + 1, width, 6, WHITE);
}
byte customChar[] = {0x1F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00};
void setup() {
Serial.begin(9600);
// initialize OLED display with address 0x3C for 128x64
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
// Инициализация пинов для AD7793
pinMode(SCLK, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(DOUT, INPUT);
digitalWrite(SCLK, HIGH);
digitalWrite(CS, HIGH);
digitalWrite(DIN, HIGH);
delay(100);
reset();
write_byte(0x08, (0x20 << 8) | F_ADC_4_17, 16); // MODE REGISTER
write_byte(0x10, ((UNIPOLAR | GAIN_1) << 8) | 0x90 | AVDD_MONITOR, 16); // CONFIGURATION REGISTER
// Калибровка
write_byte(0x08, (0xC0 << 8) | 0x0A, 16);
delay(10); // MODE REGISTER System Zero-Scale Calibration
write_byte(0x08, (0xE0 << 8) | 0x0A, 16);
delay(10); // MODE REGISTER System Full-Scale Calibration
Serial.print("Stat ");
Serial.println(read_byte(0x40, 8), BIN); // STATUS REGISTER
Serial.print("ID ");
Serial.println(read_byte(0x60, 8), BIN); // ID REGISTER
Serial.print("Ofst ");
Serial.println(read_byte(0x70, 24)); // OFFSET REGISTER
Serial.print("ful ");
Serial.println(read_byte(0x78, 24)); // FULL-SCALE REGISTER
write_byte(0x28, 0b00001011, 8); // IO REGISTER 2mA
pinMode(7, INPUT);
menu = EEPROM.read(0);
analogReference(INTERNAL);
analogRead(A0); // Холостое считывание после смены опорного напряжения
float v = (float)(analogRead(A0) * Vref / 1024) / divider;
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 25);
display.print(F("Voltage: "));
display.print(v);
display.print(F(" V"));
display.setCursor(45, 35);
display.print(F("AD7793"));
display.display();
delay(1000);
display.clearDisplay();
firstBoot = false;
}
void loop(){
if (menu != previousMenu) {display.clearDisplay(); delay(10); previousMenu = menu;} // Очистка экрана при смене меню
/// termopara //
// READ ADC //////////////////////////////////////////////////////////////////
if((millis()-times>1000||start==1)&&menu<1){
write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER
write_byte(0x10,((BIPOLAR|GAIN_16)<<8)|0x90|CH1, 16); // CONFIGURATION REGISTER
long adc = read_byte(0x58,24);
u = (1170.00/0x800000*(adc-0x800000))/16;
// BIPOLAR
Serial.print("Data b_B ");Serial.println(adc-0x800000);//DATA REGISTER
Serial.print("Data V_B ");Serial.println((1170.00/0x800000*(adc-0x800000))/16,3);//DATA REGISTER
// DS18B20
if(millis()-times>5000||start==1){temp_ds = dsRead(0);times=millis();}
start=0;
}
//TERMOMETR //
// READ ADC //////////////////////////////////////////////////////////////////
if(millis()-times>1000&&menu==1){
write_byte(0x08,(0x20<<8)|F_ADC_4_17, 16);// MODE REGISTER
write_byte(0x10,((UNIPOLAR|GAIN_1)<<8)|0x90|CH2, 16); // CONFIGURATION REGISTER
long adc = read_byte(0x58,24);
u = (1170.00/0xFFFFFF*adc)/i_1ma/2 + r_0_kall;// 2mA
if(millis()-times>5000||start==1){temp_ds = dsRead(0);times=millis();}
start=0;
// UNIPOLAR
Serial.print("Data b_U ");Serial.println(adc);//DATA REGISTER
Serial.print("Data V_U ");Serial.println((1170.00/0xFFFFFF*adc)/1,3);//DATA REGISTER
}
// LCD ///////////////////////////////////////////////////////////////////////
if (digitalRead(7) == LOW) {menu++; EEPROM.update(0, menu);}
if (menu > 1) {menu = 0;}
if (menu < 1) {
display.clearDisplay();
delay (10);
display.setCursor(5, 1);
display.print(F("T"));display.print(char(247));
display.print(F("C:"));display.print(temp_ds, 1);
display.setCursor(37, 13);display.print(F("TERMOPARA"));
display.setCursor(0, 25);display.print(F("TP: "));display.print(u, 2);
display.print(F(" mV "));
txa();
display.setCursor(0, 40); display.print(F("TXA: "));
if (t_iz == -1000) {
display.print(F("LOW "));
} else if (t_iz == 1000) {
display.print(F("HIGH "));
} else {
display.print(t_iz, 1);
display.print(char(247));
display.print(F("C "));
}
txk(); display.setCursor(0, 55); display.print(F("TXK: "));
if (t_iz == -1000) {
display.print(F("LOW "));
} else if (t_iz == 1000) {
display.print(F("HIGH "));
} else {
display.print(t_iz, 1);
display.print(char(247));
display.print(F("C "));
}
} else if (menu == 1) {
display.clearDisplay();
delay (10);
display.setCursor(0, 25);display.print(F("TC :"));
display.print(u, 2);
display.print(F(" Om "));
display.setCursor(5, 1);
display.print(F("T"));display.print(char(247));
display.print(F("C:"));display.print(temp_ds, 1);
display.setCursor(37, 13); display.print(F("TERMOMETR "));
p50();display.setCursor(0, 40); display.print(F("50P:"));
if (t_iz == -1000) {
display.print(F("LOW "));
} else if (t_iz == 1000) {
display.print(F("HIGH "));
} else {
display.print(t_iz, 1);
display.print(char(247));
}
m50(); display.setCursor(65, 40); display.print(F("50M:"));
if (t_iz == -1000) {
display.print(F("LOW "));
} else if (t_iz == 1000) {
display.print(F("HIGH "));
} else {
display.print(t_iz, 1);
display.print(char(247));
}
p21(); display.setCursor(0, 55); display.print(F("21P:"));
if (t_iz == -1000) {
display.print(F("LOW "));
} else if (t_iz == 1000) {
display.print(F("HIGH "));
} else {
display.print(t_iz, 1);
display.print(char(247));
}
m23(); display.setCursor(65, 55); display.print(F("23M:"));
if (t_iz == -1000) {
display.print(F("LOW "));
} else if (t_iz == 1000) {
display.print(F("HIGH "));
} else {
display.print(t_iz, 1);
display.print(char(247));
}
}
//BAT
int rawValue = analogRead(analogPin);
// Измерение напряжения с использованием делителя напряжения
float batteryVoltage = (rawValue * Vref / 1024.0) / divider;
int batteryLevel = map(batteryVoltage, batteryVoltageMin, batteryVoltageMax, 0, 100);
drawBatterySymbol(batteryLevel);
display.display();
delay(10);
}
void write_byte(byte reg, long data, int bit_){
digitalWrite(CS,LOW);
for(int i = 7; i >= 0; i--){
digitalWrite(SCLK,LOW);
digitalWrite(DIN, (reg >> i) & 1);
digitalWrite(SCLK,HIGH);
}
for(int i = bit_-1; i >= 0; i--){
digitalWrite(SCLK,LOW);
digitalWrite(DIN, (data >> i) & 1);
digitalWrite(SCLK,HIGH);
}
digitalWrite(CS,HIGH);
}
long read_byte(byte reg, int bit_){
digitalWrite(CS,LOW);
while(digitalRead(DOUT)!=LOW);
for(int i = 7; i >= 0; i--){
digitalWrite(SCLK,LOW);
digitalWrite(DIN, (reg >> i) & 1);
digitalWrite(SCLK,HIGH);
}
while(digitalRead(DOUT)!=LOW);
long data_out=0;
long dat;
for(int i = bit_-1; i >= 0; i--){
digitalWrite(SCLK,LOW);
digitalWrite(SCLK,HIGH);
dat = digitalRead(DOUT);
data_out |= (dat<<i);
}
digitalWrite(CS,HIGH);
return data_out;
}
void reset(){
digitalWrite(CS,LOW);
for(int i = 31; i >= 0; i--){
digitalWrite(SCLK,LOW);
digitalWrite(DIN, HIGH);
digitalWrite(SCLK,HIGH);
}
digitalWrite(CS,HIGH);
}
float dsRead(byte x) {
byte data[2], addr[8][8], kol = 0;
while (ds.search(addr[kol])) { // поиск датчиков, определение адреса и кол-ва датчиков
kol++;}
ds.reset_search(); // Сброс поиска датчика
ds.reset(); // Инициализация, выполняется сброс шины
ds.select(addr[x]); // Обращение к датчику по адресу
ds.write(0x44, 0); // Измерение температуры с переносом данных в память
ds.reset(); // Инициализация, выполняется сброс шины
ds.select(addr[x]); // Обращение к датчику по адресу
ds.write(0xBE); // Обращение памяти
data[0] = ds.read();// Чтение памяти byte low
data[1] = ds.read();// Чтение памяти byte high
float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}
void txa(){u0=u+temp_ds*0.0400;// окружающая температура 0.0400 мВ на 1 гр.Цельсия от 0 до 40 гр.Цельсия для TXA(K)
if(u0<0){t_iz=(a[0]*pow(u0,0))+(a[1]*pow(u0,1))+(a[2]*pow(u0,2))+(a[3]*pow(u0,3))+(a[4]*pow(u0,4))+(a[5]*pow(u0,5))+(a[6]*pow(u0,6))+(a[7]*pow(u0,7))+(a[8]*pow(u0,8));}
if(u0>=0&&u0<=20.64){t_iz=(a1[0]*pow(u0,0))+(a1[1]*pow(u0,1))+(a1[2]*pow(u0,2))+(a1[3]*pow(u0,3))+(a1[4]*pow(u0,4))+(a1[5]*pow(u0,5))+(a1[6]*pow(u0,6))+(a1[7]*pow(u0,7))+(a1[8]*pow(u0,8))+(a1[9]*pow(u0,9));}
if(u0>20.64){t_iz=(a2[0]*pow(u0,0))+(a2[1]*pow(u0,1))+(a2[2]*pow(u0,2))+(a2[3]*pow(u0,3))+(a2[4]*pow(u0,4))+(a2[5]*pow(u0,5))+(a2[6]*pow(u0,6));}
if(u<-6.35){t_iz=-1000;} if(u>54.9){t_iz=1000;}
}
void txk(){u0=u+temp_ds*0.06476;// окружающая температура 0.06476 мВ на 1 гр.Цельсия от 0 до 40 гр.Цельсия для TXK(L)
if(u0<0){t_iz=(b[0]*pow(u0,0))+(b[1]*pow(u0,1))+(b[2]*pow(u0,2))+(b[3]*pow(u0,3))+(b[4]*pow(u0,4))+(b[5]*pow(u0,5))+(b[6]*pow(u0,6))+(b[7]*pow(u0,7))+(b[8]*pow(u0,8))+(b[9]*pow(u0,9));}
if(u0>=0){t_iz=(b1[0]*pow(u0,0))+(b1[1]*pow(u0,1))+(b1[2]*pow(u0,2))+(b1[3]*pow(u0,3))+(b1[4]*pow(u0,4))+(b1[5]*pow(u0,5))+(b1[6]*pow(u0,6))+(b1[7]*pow(u0,7))+(b1[8]*pow(u0,8))+(b1[9]*pow(u0,9));}
if(u<-9.49){t_iz=-1000;} if(u>66.47){t_iz=1000;}
}
void p50(){if(u>=50.00){t_iz=(sqrt(0.000015752961+0.0000023364*(1-u/50.00))-0.003969 )/-0.0000011682;}
if(u<50.00){t_iz=251.903*(pow(u/50.00-1,1)) + 8.80035*(pow(u/50.00-1,2)) - 2.91506 *(pow(u/50.00-1,3)) + 1.67611*(pow(u/50.00-1,4));}
if(u<8.65){t_iz=-1000;} if(u>182.23){t_iz=1000;}
}
void p21(){if(u>=46.00){t_iz=(sqrt(0.000015752961+0.0000023364*(1-u/46.00))-0.003969 )/-0.0000011682;}
if(u<46.00){t_iz=251.903*(pow(u/46.00-1,1)) + 8.80035*(pow(u/46.00-1,2)) - 2.91506 *(pow(u/46.00-1,3)) + 1.67611*(pow(u/46.00-1,4));}
if(u<07.95){t_iz=-1000;} if(u>153.3){t_iz=1000;}
}
void m50(){if(u>=50.00){t_iz=(u/50-1)/0.00428;}
if(u<50.00){t_iz=233.87*(pow(u/50-1,1))+7.9370*(pow(u/50-1,2))-2.0062*(pow(u/50-1,3))-0.3953*(pow(u/50-1,4));}
if(u<39.24){t_iz=-1000;} if(u>92.79){t_iz=1000;}
}
void m23(){if(u>=53){t_iz=(u/53-1)/0.00426;}
if(u<53.00){t_iz=233.87*(pow(u/53-1,1))+7.9370*(pow(u/53-1,2))-2.0062*(pow(u/53-1,3))-0.3953*(pow(u/53-1,4));}
if(u<41.71){t_iz=-1000;} if(u>93.64){t_iz=1000;}
}Loading
ds18b20
ds18b20