мерцает (скачет) значение температуры на семисегментном индикаторе
- Войдите на сайт для отправки комментариев
Пт, 22/04/2016 - 21:00
Пытаюсь сдетать термометр на ардуино-нано, DS18B20, и четырехразрядном семисегментном индикаторе.
Столкнулся с проблеммой, что индикатор в основном показывает только самый левый ноль (остальные сегменты при этом не горят), и иногда (раз в секунду, после задержки), короткой вспышкой, выводит нормально температуру.
Если добавить в код вывод в последовательный порт, то в нем (в порту) все отображается корректно.
Помогите, пожалуйста, поправить так, чтобы температура показывалась постоянно.
/* - Pin d1 to digital pin 15
* - Pin d2 to digital pin 14
* - Pin d3 to digital pin 3
* - Pin d4 to digital pin 4
* - Pin a to digital pin 11
* - Pin b to digital pin 13
* - Pin c to digital pin 8
* - Pin d to digital pin 6
* - Pin e to digital pin 5
* - Pin f to digital pin 12
* - Pin g to digital pin 7
* - Pin dp to digital pin 9
*/
#include <OneWire.h>
#include <SevenSegmentDisplay.h>
SevenSegmentDisplay<false, QuadriDigit<15, 14, 3, 4> > ss(11, 13, 8, 6, 5, 12, 7, 9);
int nc;
OneWire ds(10); // датчик
byte addr[8];
byte i;
byte present = 0;
byte data[12];
int Temp10;
int znak10;
int Temp;
void setup()
{
ds.search(addr);
pinMode(3,OUTPUT); //7сегмент дисплей
pinMode(4,OUTPUT); //7сегмент дисплей
pinMode(5,OUTPUT); //7сегмент дисплей
pinMode(6,OUTPUT); //7сегмент дисплей
pinMode(7,OUTPUT); //7сегмент дисплей
pinMode(8,OUTPUT); //7сегмент дисплей
pinMode(9,OUTPUT); //7сегмент дисплей
pinMode (14, OUTPUT); //7сегмент дисплей
pinMode (15, OUTPUT); //7сегмент дисплей
}
void loop()
{
{
ds.reset(); //включаем датчик
ds.select(addr);
ds.write(0x44,1);
delay (1000); //ждем
present = ds.reset(); //опрашиваем датчик
ds.select(addr);
ds.write(0xBE);
for ( i = 0; i < 9; i++)
{
data[i] = ds.read();
}
Temp10=(data[1]<<8)+data[0];
Temp10=Temp10;
znak10=((Temp10%16)*100)/16; //вычисляем температуру
if (znak10<0)
{
znak10=znak10*-1;
}
}
unsigned z = Temp10/16;
ss.print(z); //выводим температуру на 7сегмент
}
Строка 51 -delay(1000). Используйте миллис для опроса датчика температуры.
Пробовал. Без изменений.
А если строки 48-68 закомментировать и на экране показывать просто число 321 (строку 69 заменить на ss.print(321); ) - работает? Сдаётся мне, что проблема не в замере, а в показе.
SevenSegmentDisplay на таймере работает?Строка 51 -delay(1000). Используйте миллис для опроса датчика температуры.
переписал. Стало лучше. Но теперь обратная ситуация. Нормально показывает температуру, но раз в секунду моргает всеми сегментами.
/* - Pin d1 to digital pin 15 * - Pin d2 to digital pin 14 * - Pin d3 to digital pin 3 * - Pin d4 to digital pin 4 * - Pin a to digital pin 11 * - Pin b to digital pin 13 * - Pin c to digital pin 8 * - Pin d to digital pin 6 * - Pin e to digital pin 5 * - Pin f to digital pin 12 * - Pin g to digital pin 7 * - Pin dp to digital pin 9 */ #include <OneWire.h> #include <SevenSegmentDisplay.h> SevenSegmentDisplay<false, QuadriDigit<15, 14, 3, 4> > ss(11, 13, 8, 6, 5, 12, 7, 9); int nc; OneWire ds(10); // датчик byte addr[8]; byte i; byte present = 0; byte data[12]; int Temp10; int znak10; int Temp; int flagT1=0; unsigned long currentTime=0; unsigned long tTime=0; void setup() { ds.search(addr); pinMode(3,OUTPUT); //7сегмент дисплей pinMode(4,OUTPUT); //7сегмент дисплей pinMode(5,OUTPUT); //7сегмент дисплей pinMode(6,OUTPUT); //7сегмент дисплей pinMode(7,OUTPUT); //7сегмент дисплей pinMode(8,OUTPUT); //7сегмент дисплей pinMode(9,OUTPUT); //7сегмент дисплей pinMode (14, OUTPUT); //7сегмент дисплей pinMode (15, OUTPUT); //7сегмент дисплей } void loop() { currentTime = millis(); //запускаем счетчик { if(flagT1==0) { ds.reset(); //включаем датчик ds.select(addr); ds.write(0x44,1); flagT1=1; } if((flagT1==1)&&(currentTime>=(tTime+1000))) //ждем { present = ds.reset(); //опрашиваем датчик ds.select(addr); ds.write(0xBE); for ( i = 0; i < 9; i++) { data[i] = ds.read(); } Temp10=(data[1]<<8)+data[0]; Temp10=Temp10; znak10=((Temp10%16)*100)/16; //вычисляем температуру if (znak10<0) { znak10=znak10*-1; } flagT1=0; tTime=currentTime; } } unsigned z = Temp10/16; ss.print(z); //выводим температуру на 7сегмент }если ss.print поставить один раз в setup, а строку 81 закоментировать дисплей что будет показывать?
А если строки 48-68 закомментировать и на экране показывать просто число 321 (строку 69 заменить на ss.print(321); ) - работает? Сдаётся мне, что проблема не в замере, а в показе.
тоже метцает.
С другой стороны, если меняю датчик температуры на переменный резистор, то все отлично работает и не мерцает.
Похоже на конфликт с датчиком.
если ss.print поставить один раз в setup, а строку 81 закоментировать дисплей что будет показывать?
поставил ss.print в setup, а строку 81 закоментировал "1234"
результат - компилятор выдал ошибку "exit status 1 'z' was not declared in this scope"
поставил ss.print и строку 81 в setup, строку 81 (уже в setup) закоментировал "1234"
результат - на дисплее один раз моргнуло "1234", и сразу "234" погасло, а осталось только "1"
SevenSegmentDisplay на таймере работает?если залить пример из библиотеки SevenSegmentDisplay , то отлично отсчитывает цифры
/*! * \file QuadriDigit.ino * \brief demo for four 7-segement displays with common cathode. * \author Like Ma <likemartinma@gmail.com> * * This sketch counts down from 9999 to 0, while each value keeps displaying for 0,05 seconds. * The circuit: * - Pin d1 to digital pin 15 * - Pin d2 to digital pin 14 * - Pin d3 to digital pin 3 * - Pin d4 to digital pin 4 * - Pin a to digital pin 11 * - Pin b to digital pin 13 * - Pin c to digital pin 8 * - Pin d to digital pin 6 * - Pin e to digital pin 5 * - Pin f to digital pin 12 * - Pin g to digital pin 7 * - Pin dp to digital pin 9 */ #include <SevenSegmentDisplay.h> SevenSegmentDisplay<false, QuadriDigit<15, 14, 3, 4> > ss(11, 13, 8, 6, 5, 12, 7, 9); void setup() { } void loop() { unsigned i = 9999; do { ss.print(i, -1, 50); } while (i--); }я к чему спрашиваю
нормальное отображение с динамической индикацией требует чтобы обновление информации делалось со строго равными интерваламми времени, это можно сделать только в прерывании по таймеру
у меня нет этой библиотнки и я не знаю как она организована
по тому что вы написали похоже на то, что регулярность отображения нарушена, это происходит или потому, что библиотека не использует прерывания или потому, что кто то мешает прерываниям
пока не ясно. то есть у вас после того, что я попросил отображается только первая цифра, так?
Да. Сначала вспыхивают все цифры, и сразу три гаснут. Остается гореть только первая.
У вас сканирование как устроено? Что за дисплей?
Про сканирование не понял. Что это?
Дисплей примерно такой http://files.freks.webnode.com/200001866-60ade62a27/7segm_ind.jpg
динамическая индикация http://we.easyelectronics.ru/Shematech/dinamicheskaya-indikaciya_2.html
как дисплей подключен?
Подключен напрямую к ардуино (через резисторы) без драйверов.
Индикация динамическая, поразрядная.
В скетче, в начале, все пины описаны.
использована эта библиотека
/*! * \file SevenSegmentDisplay.h * \brief Arduino 7-Segment Display * \author Like Ma <likemartinma@gmail.com> */ #ifndef SEVENSEGMENTDISPLAY_H #define SEVENSEGMENTDISPLAY_H #if defined(ARDUINO) && ARDUINO >= 100 # include "Arduino.h" #else # include "WProgram.h" #endif template <byte D1> struct UniDigit { enum { N = 1 }; static byte pin[N]; }; template <byte D1, byte D2> struct BiDigit { enum { N = 2 }; static byte pin[N]; }; template <byte D1, byte D2, byte D3> struct TriDigit { enum { N = 3 }; static byte pin[N]; }; template <byte D1, byte D2, byte D3, byte D4> struct QuadriDigit { enum { N = 4 }; static byte pin[N]; }; template <boolean ANODE, typename DIGITS, unsigned DELAY = 20> class SevenSegmentDisplay { public: /*! * \brief Initialize 7-segment display. * * See the following ascii diagram for parameters: * * a * _____ * | | * f | g | b * |_____| * | | * e | | c * |_____| . dp * * d */ SevenSegmentDisplay(byte a, byte b, byte c, byte d, byte e, byte f, byte g, byte dp); /*! * \brief Display fixed point number. * \param n The number to display. * \param pt The position of the point ranged from 0 to DIGITS::N - 1, while 0 denotes the lowest digit. * \param duration The duration for displaying. */ void print(unsigned n, byte pt = -1, unsigned long duration = 0); /*! * \brief Display float point number. * \param n The number to display. * \param duration The duration for displaying. */ void print(float n, unsigned long duration = 0); /*! * \brief light off all segments. */ void clear (); protected: void pickDigit(byte i); void printDigit(byte n, bool dp = false); void printUnsigned(unsigned n, byte dp); void printFloat(float n); enum { MAX_SEGMENTS = 8, DP_IDX = MAX_SEGMENTS - 1 }; byte pin_[MAX_SEGMENTS]; byte digit_[10]; }; #include "SevenSegmentDisplay.inl" #endif /* SEVENSEGMENTDISPLAY_H */сделал индикацию без библиотек, с выводом в порты В и D.
показывает нормально, но раз в секунду моргает.
как убрать это моргание?
#include <OneWire.h> int nc; OneWire ds(14); // датчик byte addr[8]; byte i; byte present = 0; byte data[12]; int Temp14; int znak14; int Temp; int flagT1=0; unsigned long currentTime=0; unsigned long tTime=0; int x; int tys; int sot; int des; int ed; byte t=0, s=0, e=0, d=0, a=0; //объявляем переменные единиц, десятков, сотен, тысяч переменную мерцания byte cif[10]={252,96,218,242,102,182,190,224,254,246}; // массив цифр void setup() { DDRD=255; // пины порта D и B обозначаем выходными DDRB=63; ds.search(addr); pinMode (14, INPUT); //7сегмент дисплей } void loop() { currentTime = millis(); //запускаем счетчик { if(flagT1==0) { ds.reset(); //включаем датчик ds.select(addr); ds.write(0x44,1); flagT1=1; } if((flagT1==1)&&(currentTime>=(tTime+1000))) //ждем { present = ds.reset(); //опрашиваем датчик ds.select(addr); ds.write(0xBE); for ( i = 0; i < 9; i++) { data[i] = ds.read(); } Temp14=(data[1]<<8)+data[0]; Temp14=Temp14; znak14=((Temp14%16)*100)/16; //вычисляем температуру if (znak14<0) { znak14=znak14*-1; } flagT1=0; tTime=currentTime; } } x=Temp14/16; tys=x/1000; sot=(x-tys*1000)/100; des=(x-tys*1000-sot*100)/10; ed=(x-tys*1000-sot*100-des*10); PORTB=62; // активируем разряд тысяч PORTD=cif[tys]; // пишем нужную цифру тысяч в порт D delay(6); // пауза, чтобы сегменты "разгорелись" PORTB=61;// активируем разряд сотен PORTD=cif[sot]; // пишем нужную цифру сотен в порт D delay(6);// пауза, чтобы сегменты "разгорелись" PORTB=59;// пишем нужную цифру десятков в порт D PORTD=cif[des]; // пишем нужную цифру десятка в порт D delay(6);// пауза, чтобы сегменты "разгорелись" PORTB=55;// пишем нужную цифру единиц в порт D PORTD=cif[ed]; // пишем нужную цифру единиц в порт D delay(6);// пауза, чтобы сегменты "разгорелись" }Обновление цифр необходимо делать в прерывании
посмотрите библиотеку mstimer2
У вас вывод как организован? За один проход одна цифра или за один проход один сегмент сразу на всех цифрах?
В строке 47 у тебя заложены "грабли", надо делать так: (currentTime-tTime>=1000)