Вольтметр с 7seg и MAX7219

cucumber
Offline
Зарегистрирован: 27.10.2019

Пытаюсь извернуться с выводом измеренного напряжения на 7 сегментный индикатор. Как вывести число с плавающей точкой не разобрался и решил перемножить все до целых чисел и управлять точкой по условию. Вроде даже все получилось, но если изменить разрядность с 10 бит(1023) на 11, 12..16 - показания уплывают и  глаз уже замылился окончательно, не могу понять куда копать. 
Моделирую все в протеусе. В итоге планируется ацп ADS1115, который на 16 бит, но его макроса не нашел, потому решил с обычным входом протестить, а потом уже с большей точностью, ну вот на этом все и посыпалось. Хочу разобраться что не так или может найти рабочий способ выводить  float на 7 сегментный индикатор. Гуглил и не нагуглил. Помогите

/* 
#define NUMBEROFDRIVERS 1 <- Change this number

PINOUT:

MODULE.....UNO/NANO.....MEGA
VCC........+5V..........+5V
GND........GND..........GND
DIN........11...........51
CS (LOAD)..10...........10
CLK........13...........52

/* Include the HCMAX7219 and SPI library */
#include <HCMAX7219.h>
#include "SPI.h"

#define LOAD 10
 
HCMAX7219 HCMAX7219(LOAD);
int u = 0; // переменная для числа преобразования 0-1023
//unsigned int u_in = 0; // переменная для напряжения
float u_in = 0.0;


void setup() 
{   pinMode(A0,INPUT);// A0 - аналоговый вход       
//Serial.begin (9600); 
}

/* Main program */
void loop() 
{
  
  u = analogRead(A0); // измерение по входу А0
  u_in = ((u * 49.99999999999) / 1023) *1000; // пересчет измерения в вольты (на Uвх = 5 В)

  delay(20);

if (u_in<=100) { 
  HCMAX7219.Clear();
  HCMAX7219.print7Seg("O",4);
  HCMAX7219.print7Seg("O",3,3);
  //HCMAX7219.Refresh(); 
  HCMAX7219.print7Seg(u_in,2);
 
  HCMAX7219.Refresh();  
  
  while(1);
  delay(10);}
 
 if (u_in>100&&u_in<1000){
 HCMAX7219.Clear();
 HCMAX7219.print7Seg("0",3,4);
 HCMAX7219.print7Seg(u_in,3);
  // Send the output buffer to the display //
 HCMAX7219.Refresh();  

  while(1);
  delay(10);}

 if (u_in>1000&&u_in<10000){ 
  
 HCMAX7219.Clear();

 HCMAX7219.print7Seg(u_in,3,4);
  // Send the output buffer to the display //
  HCMAX7219.Refresh(); 

  while(1);
  delay(10);}

 else if (u_in>10000){ 
  
 HCMAX7219.Clear();

 HCMAX7219.print7Seg(u_in,3,4);

 HCMAX7219.Refresh(); 

  while(1);
  delay(10);}
 
}

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

35 строка не ясна ! умножили на 10 (49.9999 вместо 4.9999) потом еще на 1000

rkit
Offline
Зарегистрирован: 23.11.2016

А с чего ты решил, что в ацп больше 10 бит?

cucumber
Offline
Зарегистрирован: 27.10.2019

49.9999 - представил пересчет после делителя на 10, (вообще конечно должно быть ровно 50, но с целым отказывался работать по неясной причине), умножил на 1000 чтобы гарантировано  избавиться от запятой.. 
rkit, https://radiolaba.ru/microcotrollers/ads1115-opisanie-i-podklyuchenie-16-bitnogo-atsp.html

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Надо не 50, а 50.0 тогда уж.

cucumber
Offline
Зарегистрирован: 27.10.2019

согласен, работает, но основная проблема остается...

Green
Offline
Зарегистрирован: 01.10.2015

Как то не аккуратненько.

#define R1                13.0
#define R2                4.7
#define V_REF             5000
#define ADC_RESOLUTION    1024
#define K_DIVIDER         ((R1 + R2) / R2)
#define ADC2MV(adc)       ((adc * (uint32_t)(K_DIV * V_REF)) / ADC_RESOLUTION)

 

b707
Offline
Зарегистрирован: 26.05.2017

cucumber пишет:

согласен, работает, но основная проблема остается...

в чем проблема-то?

Pyotr
Offline
Зарегистрирован: 12.03.2014

Вообще то правильней значение АЦП переводить в напряжение так

u_in = Vref / 1024 * (ADC + 0.5); //Vref = 5 В в вашем случае

Green
Offline
Зарегистрирован: 01.10.2015

Это если Vref с плавающей точкой.

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

cucumber пишет:

рабочий способ выводить  float на 7 сегментный индикатор

А если вообще отказаться от флоат? Штука медленная, жручая в смысле памяти. Может, через оператор "map" масштабировать данные аналогового входа (0-1023), скажем, в милливольты (0-5000). Спокойно и без флоатовских изысков работаем с переменной типа int. А децимальную точку просто поставить в левом разряде навсегда.

PS: Друзья, я ничего не ляпнул криминального по своему обыкновению?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Ляпнул ... у ТС делитель еще 10:1 и целых разрядов до двух ...

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

Komandir пишет:

у ТС делитель еще 10:1 и целых разрядов до двух ...

Ну и что? Принцип-то остается. Только расположение точки будет меняться в зависимости от величины измеренного напряжения. Пара строчек в скетче. И только.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

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

b707
Offline
Зарегистрирован: 26.05.2017

Sonologist пишет:

А если вообще отказаться от флоат? Штука медленная, жручая в смысле памяти. Может, через оператор "map" масштабировать данные

можно и отказаться, только не совсем не так, как вы пишете. Зачем чего-то масштабировать с помощью MAP, если и АЦП ардуины, и ADS1115 - сразу выдают результат в целых числах?

ТС куда-то пропал и не отвечает... он так и не обьяснил, в чем вообще проблема вывести любое число (что целое. что флоат) - на индикатор? В инете куча примеров разбиения числа на разряды... А может ТС уже давно все решил. а мы тут спорим.

Green
Offline
Зарегистрирован: 01.10.2015

Sonologist пишет:
А если вообще отказаться от флоат? Штука медленная, жручая в смысле памяти. Может, через оператор "map" масштабировать данные аналогового входа (0-1023), скажем, в милливольты (0-5000). Спокойно и без флоатовских изысков работаем с переменной типа int. А децимальную точку просто поставить в левом разряде навсегда.

ТС вроде как так и хочет. Я все формулы привёл. Минимум - минимор, без флоатов и мапов. Только точку рисуй.

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

b707 пишет:

Sonologist пишет:

А если вообще отказаться от флоат? Штука медленная, жручая в смысле памяти. Может, через оператор "map" масштабировать данные

можно и отказаться, только не совсем не так, как вы пишете. Зачем чего-то масштабировать с помощью MAP, если и АЦП ардуины, и ADS1115 - сразу выдают результат в целых числах?

Немного смутила у ТС 35-я строчка:  "((u * 49.99999999999) / 1023) *1000;" То есть, входные цифры (целые, дробные...) делить на 1023, умножать на 1000 и априри получать дробное число. МАР это делает изящнее (уверен, что точность до 1/1000 вольта не требовалась). Лады, спорить не будем. Нет смысла.