Помогите с вольтметром SSD1306

Всем привет. Сделал вольтметр на SSD1306, но возникло ряд вопросов как повысить его точность и как вывести в нижней строке при напряжении от 2 до 3 вольт надпись STOP и на один цифровой выход для индикации светодиодом


#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4


int analogInput = 0;               // переменная для удобства инициализации и работы с аналог. портом 0
float vout = 0.0;                  // переменная с значением выходного напряжения  
float vin = 0.0;                   // переменная с результатом измерений
float R1 = 100000.0;               // сопротивление R1
float R2 = 10000.0;                // сопротивление R2
int value = 0;                     // переменная хранения данных 
Adafruit_SSD1306 display(OLED_RESET);
void setup(){ 
  pinMode(analogInput, INPUT);   // инициализируем аналоговый порт 0, как вход 
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
  delay(20);
  display.clearDisplay();}
void loop() {                      // производим чтение аналогового сигнала и выводим на дисплей
 
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
   value = analogRead(analogInput);// читаем аналоговый сигнал, с аналог. порта - 0 
   vout = (value * 5.0) / 1024.0;  // не забываем про внесение поправки (5.0 - это идеальный вариант,хотя все возможно)
   vin = vout / (R2/(R1+R2));      // в переменной будет значение входного напряжения
   if (vin<0.09)                   // проверка, для получ. 0
  {   
   vin=0.0;                        // обнуляем нежелательное значение
   }   
   display.print("U = ");
   display.print(vin);
   display.println(" ");
   display.println("volt");
   display.display();
   delay(500);
}

Для точности надо точные резисторы и в 27 строке 5.0 изменить на реально измеренное значение питания. Еще - если вы знаете пределы измеряемого напряжения, то можно изменить или совсем убрать делитель из резисторов.
Для Stop:
между 36 и 37 вставить проверку напряжения и в зависимости от результата выводить надпись и зажигать диод или выводить пробелы и тушить диод.

if ((vin>=2.00) && (vin<=3.00))
  {   
     Печатаем Stop
     Зажигаем диод
   } else
   {
      Печатаем несколько пробелов что бы затереть Stop
      Гасим диод
   }

Не использовать значение 5В, а реально измерять напряжение питания каждый раз перед замером измеряемого напряжения.

Измеряемое напряжение до 20В

Можете подсказать как это сделать?

Можно взять резисторы 5 к 1 и предел будет от 0 до 25 вольт - точные номиналы прописать в формулу.

Да, не вопрос, а если Вы скажете, что у Вас за контроллер, так и куском кода могу поделиться.

А как это сделать написано у Гэммона, поищите там заголовок “Detecting low voltage”

Arduino Nano

float Vop= (float)(1.1*1023)/analogRead(14)
и вместо 5.0 вставить Vop

После сокращения
vout = analogRead(analogInput)*1.1/analogRead(14)

При этом ничего не выводит

Вы новый код покажите … хз что вы там куда присунули …

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4


int analogInput = 0;               // переменная для удобства инициализации и работы с аналог. портом 0
float Vop= (float)(1.1*1023)/analogRead(0);
float vout = 0.0;                  // переменная с значением выходного напряжения  
float vin = 0.0;                   // переменная с результатом измерений
float R1 = 100000.0;               // сопротивление R1
float R2 = 10000.0;                // сопротивление R2
int value = 0;                     // переменная хранения данных 
Adafruit_SSD1306 display(OLED_RESET);
void setup(){ 
  pinMode(analogInput, INPUT);   // инициализируем аналоговый порт 0, как вход 
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
  delay(20);
  display.clearDisplay();}
void loop() {                      // производим чтение аналогового сигнала и выводим на дисплей
 
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
   value = analogRead(analogInput);// читаем аналоговый сигнал, с аналог. порта - 0 
   vout = (value * Vop) / 1024.0;  // не забываем про внесение поправки (5.0 - это идеальный вариант,хотя все возможно)
   vin = vout / (R2/(R1+R2));      // в переменной будет значение входного напряжения
   if (vin<0.09)                   // проверка, для получ. 0
  {   
   vin=0.0;                        // обнуляем нежелательное значение
   }   
   display.print("U = ");
   display.print(vin);
   //display.println(" ");
   //display.println("volt");
   display.display();
   delay(50);
}

как то мои 14 превратились в 0

Поменял на 14 и вместо напряжения пишет inf

в 28 строке напишите
vout = 1.1*analogRead(analogInput)/analogRead(14)

Теперь на экран выводит неправильное значение

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4


int analogInput = 0;               // переменная для удобства инициализации и работы с аналог. портом 0
float Vop= (float)(1.1*1023)/analogRead(14);
float vout = 0.0;                  // переменная с значением выходного напряжения  
float vin = 0.0;                   // переменная с результатом измерений
float R1 = 100000.0;               // сопротивление R1
float R2 = 10000.0;                // сопротивление R2
int value = 0;                     // переменная хранения данных 
Adafruit_SSD1306 display(OLED_RESET);
void setup(){ 
  pinMode(analogInput, INPUT);   // инициализируем аналоговый порт 0, как вход 
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
  delay(20);
  display.clearDisplay();}
void loop() {                      // производим чтение аналогового сигнала и выводим на дисплей
   display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
   value = analogRead(analogInput);// читаем аналоговый сигнал, с аналог. порта - 0 
   vout = 1.1*analogRead(analogInput)/analogRead(14);  // не забываем про внесение поправки 
   vin = vout / (R2/(R1+R2));      // в переменной будет значение входного напряжения
   if (vin<0.09)                   // проверка, для получ. 0
  {   
   vin=0.0;                        // обнуляем нежелательное значение
   }   
   display.print("U = ");
   display.print(vin);
   //display.println(" ");
   //display.println("volt");
   display.display();
   delay(50);
}

не помогло((

Я просто забыл что без исправление wiring.c не прочитать нужный вход АЦП…

Тута мысля пришла- а если делать несколько измерений
типа

analogReference(INTERNAL);
if(analogRead(AX)<512&&analogRead(AX)>205)
{
 analogReference(INTERNAL2V56); 
 result=analogRead(AX);
 analogReference(INTERNAL);
}
else if(analogRead(AX)<205)
{
 analogReference(INTERNAL1V1); 
 result=analogRead(AX);
 analogReference(INTERNAL);
}
result=analogRead(AX);

Евгений Петрович как-то уже приводил код для контроля напряжения питания

//
// Возвращает напряжение питания в десятых долях вольта
// Параметр - внутреннее опорное напряжение, умноженное на 10000
// Внутреннее опорное напряжение нужно замерить с как можно большей точностью
//
inline static int getBatteryVoltage(const int internalRefference = 11000) {
  ADCSRA = (bit(ADPS2) | bit(ADPS1) | bit(ADPS0));
  ADCSRA |= bit(ADEN);
  ADMUX = 0;
  ADCSRB = 0;
  ADMUX = (ADMUX & 0x2F) | 0x40;
  ADMUX &= ~bit(ADLAR);
  ADMUX = (ADMUX & 0xF0) | 14;
  delay(1); // пусть "пропитается"
  for (ADCSRA |= bit(ADSC); ADCSRA & bit(ADSC);); // Первый замер ни о чём
  for (ADCSRA |= bit(ADSC); ADCSRA & bit(ADSC);); // Замеряем
  while (ADCSRA & bit(ADSC));
  const int adc = ADC;
  return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}


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

void loop(void){
  Serial.println(getBatteryVoltage(10522)); // внутреннее опорное напряжение 1,0522В
  delay(2000);
}

// при напряжении питания 4.5В выводит 45