Ви не увійшли.
Сторінки 1
Зараза... ПРОСЫПАЕТСЯ ровно с трёх вольт! При плавном повышении. Как и прописано в дефайне:
#define battery_min 3000
А засыпать при плавном понижении не хочет. Плавное понижение напряжения приводит к плавному затуханию ЖКИ и "заморозке" выводимых цифр.
зы: Этот кусок вообще не работает. (( Изменяю "3000" на "2700", потом на "3500" - всё равнобедренно: просыпается примерно ровно на трёх вольтах...
Поменял знак "<" в
if (analogRead(batPin) < battery_min)
на ">", получилось
if (analogRead(batPin) > battery_min)
- появилось изображение на экране, подсветка работает адекватно... Вышеозначенный кусок сейчас вставлен в конец "Сетапа". Проверяю лабораторным БП, с плавной регулировкой напруги...
А вот строчки из проекта "Предсказатель погоды" Александра Гайвера, которые погружают устройство в вечный сон по достижении минимально допустимого напряжения на аккумуляторе:
if (analogRead(batPin) < battery_min) LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // вечный сон если акум сел
wake_flag = 0;
delay(10);
Пытался вставлять эту конструкцию, объявив соотв. переменные, в разные места исходника. Но в итоге неизменно получаю пустой экран с постоянно включенной подсветкой... Караул!
Здравствуйте, уважаемые участники. Ниже - немножко подпиленный код из одноимённого топика на форуме ардуино.ру, адаптированный под свои нужды.
Всё работает, кроме одного - не засыпает (с потреблением единиц микроампер) по достижении заданного в скетче минимального напряжения на литиевом аккумуляторе 14500. Ток потребления остаётся в районе нескольких сот микроампер, причём до "полного не могу", уже с потухшим дисплеем, проваливая напругу на аккумуляторе глубоко ниже 2 В...
Пробовал разбираться с библиотекой LowPower. Пытался, "по образцу и подобию", вставлять строчки из скетча гайверовского "Предсказателя погоды" (там тоже используется эта же библиотека), но что-то ничего не выходит... Всё компилируется без замечаний, но устройство продолжает потреблять значительный ток при напряжении питания ниже заданного порога, с уже погасшим экраном. Ниже привожу рабочий исходник, без моих правок, в котором работает всё, кроме вечного сна. Может кому-то покажется интересным для повторения. Буду благодарен за любую помощь.
#include <LCD5110_Graph.h> // rinkydinkelectronics.com/library.php
#include <Wire.h>
#include <Adafruit_BMP085.h> // github.com/adafruit/Adafruit-BMP085-Library
#include <LowPower.h> // github.com/rocketscream/Low-Power
Adafruit_BMP085 dps;
// ********** Опции компиляции **************
//#define SeaLevel // раскоментировать для коррекции на высоту
//#define debug // для тестирования графиков (ан.вход a1 как задатчик давления)
#define cont 67 // для изменения раскоментировать эту строку (70 по умолчанию)
#define zapolnen // Заполнение графика 1
//#define gasim_lcd // если экономим батарейки гашением LCD
long P_win = 165 * 133.3; // Верхняя граница абс. графика по умолчанию до сдвига (600 + 165) = 765мм
#if defined (SeaLevel) // если не включена коррекция, экономим память
float Alt_corr = 32.4; // Коррекция высоты в метрах.
#endif
uint32_t Pressure;
float temp;
unsigned char sotki ; // сотые для давления
unsigned char p_count, p2;
long P_Min, P_Max, P_Dt, P_Mid;
uint16_t P_Mem[217]; //-79980 = 600мм (3 day 20min memory, 72 per 24 hour)
signed char x, y, last_x, last_y;
// nokia 5110 connect
// pin d3 - Serial clock out (SCLK)
// pin d4 - Serial data out (DIN)
// pin d5 - Data/Command select (D/C)
// pin d6 - LCD reset (RST)
// pin d7 - LCD chip select (CS)
LCD5110 myGLCD(3, 4, 5, 6, 7);
// bmp180 connect
// sda - a4
// scl - a5
// Use pin 2 as wake up pin
const char wakeUpPin = 2; // d2 для кнопки
const char lightPin1 = 12; // d11 подсветка дисплея
const char lightPin2 = 11; // d12 инверсная подсветка дисплея
const char batPin = 0; // a0 - ан. вход для контроля батареи 220к/51к
volatile char scr_num = 0; // Номер экрана для отображения
volatile boolean key_pressed = false; // Признак что кнопку жали
volatile boolean in_int = false; // Признак нахождения в прерывании
volatile boolean Refresh = true; // Признак что нужно обновить отрисовку (для экономии батарей)
volatile boolean Lcd_On = true; // Признак что дисплей включен
volatile char light_on = 1; // длительность подсветки при включении 4*4 = 16с.
extern unsigned char BigNumbers[];
extern unsigned char MediumNumbers[];
extern unsigned char SmallFont[];
extern unsigned char TinyFont[]; // внешние шрифты
unsigned char tik = 0; // счетчики для времени
unsigned char Count_Minute = 0;
uint32_t Son_count = 0;
//******************************** START ***************************************
void setup() {
myGLCD.InitLCD();
#if defined (cont)
myGLCD.setContrast(cont); //регулировка контраста при необходимости
#endif
myGLCD.setFont(SmallFont);
Wire.begin();
analogReference(INTERNAL); //1.1v internal op.source
pinMode(batPin,INPUT); //Вход для контроля батареи
#if defined (debug)
pinMode(1,INPUT); // а1 - задание давления
analogRead(1);
#endif
LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
//dps.begin(BMP085_ULTRALOWPOWER);
dps.begin(BMP085_STANDARD);
//dps.begin(BMP085_HIGHRES);
//dps.begin(BMP085_ULTRAHIGHRES);
pinMode(wakeUpPin, INPUT); // Configure wake up pin as input.
digitalWrite(wakeUpPin, 1); // pullup
pinMode(lightPin1, OUTPUT);// lcd light pin as output;
pinMode(lightPin2, OUTPUT);// lcd light inv pin as output;
#if defined (SeaLevel)
Pressure = dps.readSealevelPressure(Alt_corr); // с коррекцией на уровень моря
#else
Pressure = dps.readPressure(); // без коррекции к уровню моря
#endif
P_Mid = Pressure - 79980; // (79980 = 600mm) отсекаем лишнее
P_Mem[p_count] = P_Mid; // заносим в память первое значение давления для правильной работы усреднения
// Serial.begin(9600);
// while (!Serial) ; // wait for Arduino Serial Monitor
// delay(200);
}
void loop() { // *********************************************************
// Allow wake up pin to trigger interrupt on low.
#if defined (debug)
#else
if ((Son_count < 5)||((!(Son_count % 5))&&(tik==0))) { // через 5 минут активности, не заходим в тело по 5 минут
#endif
// Serial.print("S=");Serial.print(Son_count);Serial.print(" %=");Serial.println(Son_count % 5);
detachInterrupt(0); // запрет прерываний
#if defined (SeaLevel)
Pressure = dps.readSealevelPressure(Alt_corr); // с коррекцией на уровень моря
#else
Pressure = dps.readPressure()+0; // без коррекции к уровню моря; "-73" = коррекция данных давления (подставить нужный знак и число Па)
#endif
temp = dps.readTemperature()-0; // "-0.5" = коррекция данных температуры (подставить нужный знак и число градусов Цельсия)
attachInterrupt(0, wakeUp, LOW); // восстановить прерывания от кнопки
#if defined (debug)
Pressure = map(analogRead(1),0,1023,730*133.3,790*133.3); // для отладки резистор на а1 - задатчик давления
#endif
// для экранов с инверсным подсветом использовать lightPin2
if (light_on > 0) {
digitalWrite(lightPin1, 1);digitalWrite(lightPin2, 0);
light_on--;
}
else {digitalWrite(lightPin1, 0);digitalWrite(lightPin2, 1);} // lcd light on/off
if (Pressure > 79900){ // 600mm
P_Mid = (P_Mid + (Pressure - 79980))/2; // усреднение замеров, отбрасываем показания ниже 600мм.(сбоит бывает)
}
#if defined (debug)
if (Count_Minute >= 2){ Refresh = true; // раз в секунду
#else
if (Count_Minute >= 20){ Refresh = true; // каждые 20 мин. запоминаем усредненное значение в память и обновляем графики
#endif
if (p_count == 216) {
for (int i = 0; i < 216; i++) // сдвигаем если буфер полон
{
P_Mem[i] = P_Mem[i+1];
}
}
else {
p_count++;
}
P_Mem[p_count] = P_Mid;
if (Pressure > 79980){
P_Mid = Pressure - 79980; // новый старт усреднения
}
Count_Minute = 0;
}
#if defined (gasim_lcd)
if ((Son_count < 3)&&(!Lcd_On)) {myGLCD.disableSleep(); Lcd_On = true;} // Если разрешено, гасим дисплей через 15 мин.
if ((Son_count >= 3)&&(Lcd_On)) {myGLCD.enableSleep(); Lcd_On = false;}
#endif
// Отображение экранов
if (Lcd_On) {switch (scr_num)
{
case 0: // summary screen
Refresh = true; // Обновить отрисовку каждый цикл
myGLCD.clrScr(); // Очистка экрана
myGLCD.setFont(BigNumbers);
//Давление с BMP180
myGLCD.printNumI((Pressure / 133.3), 15, 5, 3); //расчет атмосферного давления;
myGLCD.setFont(SmallFont);
myGLCD.print(".", 57, 22);
sotki = ((Pressure / 133.3)-int(Pressure / 133.3))*100;
myGLCD.printNumI((sotki / 10), 63, 22, 1);// десятые;
myGLCD.printNumI((sotki % 10), 69, 22, 1);// сотые
myGLCD.print("Hg", 63, 6);
myGLCD.print("C", 29, 35);
myGLCD.printNumF(temp, 1, LEFT, 35); //температура
myGLCD.print("V", RIGHT, 35);
myGLCD.printNumF(analogRead(batPin)/176.5, 2, 53, 35); //напряжение питания (коэффициент xxx.x подбирается, точка и десятые обязательны)
//одна единица коэффициента (ххХ.х) =~ 0,02 В; (чем коэффициент >, тем напряжение <)
myGLCD.setFont(TinyFont);
myGLCD.print("o", 26, 33);
break;
case 1: // давление в кПа *****************************************************
Refresh = true; // Обновить отрисовку каждый цикл
myGLCD.clrScr(); // Очистка экрана
myGLCD.setFont(MediumNumbers);
//Давление с BMP180
myGLCD.printNumI(Pressure, CENTER, 1); //расчет атмосферного давления;
myGLCD.setFont(SmallFont);
//myGLCD.print(".", 57, 22);
// sotki = ((Pressure/1) - int (Pressure/1))*100;
//myGLCD.printNumI((sotki / 10), 63, 22, 1);// десятые;
// myGLCD.printNumI((sotki % 10), 69, 22, 1);// сотые
myGLCD.print("Pa", CENTER, 22);
myGLCD.print("C", 29, 35);
myGLCD.printNumF(temp, 1, LEFT, 35); //температура
myGLCD.print("V", RIGHT, 35);
myGLCD.printNumF(analogRead(batPin)/176.5, 2, 53, 35); //напряжение питания (коэффициент xxx.x подбирается, точка и десятые обязательны)
//одна единица коэффициента (ххХ.х) =~ 0,02 В; (чем коэффициент >, тем напряжение <)
myGLCD.setFont(TinyFont);
myGLCD.print("o", 26, 33);
break;
case 2: // график давления за сутки с масштабированием
if (Refresh){ // Рисуем если разрешено обновить
P_Min = P_Mem[p_count];
P_Max = P_Min; // сбросить значения
if (p_count < 72) {
p2 = 0;
}
else {
p2 = p_count - 72;
}
for (int i=p_count; i>p2 ; i--) {
if (P_Min > P_Mem[i]) {
P_Min = P_Mem[i];
}
if (P_Max < P_Mem[i]) {
P_Max = P_Mem[i];
}
}
P_Dt = P_Max - P_Min; // макс. разница
myGLCD.clrScr(); // Очистка экрана
myGLCD.setFont(TinyFont); // Установка набора символов
x=77;
if (P_Dt > 0){
for (int i=p_count; i>p2 ; i--) {
y = ((36 * (P_Max - P_Mem[i]))/P_Dt)+6;
if (x == 77) {
myGLCD.setPixel(x, y);
}
else {
myGLCD.drawLine(last_x, last_y, x, y);
}
last_x = x;
last_y = y;
x--;
}
}
myGLCD.print("Max:", LEFT, 0);
myGLCD.printNumF((P_Max +79980)/ 133.3, 2, 20, 0);
myGLCD.print("24 Hrs", RIGHT, 0);
myGLCD.print("Min:", LEFT, 42);
myGLCD.printNumF((P_Min+79980) / 133.3, 2, 20, 42);
}
break;
case 3: // график давления за трое суток
if (Refresh){ // Рисуем если разрешено обновить
P_Min = P_Mem[p_count];
P_Max = P_Min; // сбросить значения
for (int i=p_count; i>0 ; i = i - 3) {
if (P_Min > P_Mem[i]) {
P_Min = P_Mem[i];
}
if (P_Max < P_Mem[i]) {
P_Max = P_Mem[i];
}
}
P_Dt = P_Max - P_Min; // макс. разница
myGLCD.clrScr(); // Очистка экрана
myGLCD.setFont(TinyFont); // Установка набора символов
x=77;
if (P_Dt > 0){
for (int i=p_count; i>0 ; i = i - 3) {
y = ((36 * (P_Max - P_Mem[i]))/P_Dt)+6;
if (x == 77) {
myGLCD.setPixel(x, y);
}
else {
myGLCD.drawLine(last_x, last_y, x, y);
}
last_x = x;
last_y = y;
x--;
}
}
myGLCD.print("Max:", LEFT, 0);
myGLCD.printNumF((P_Max +79980)/ 133.3, 2, 20, 0);
myGLCD.print("72 Hrs", RIGHT, 0);
myGLCD.print("Min:", LEFT, 42);
myGLCD.printNumF((P_Min+79980) / 133.3, 2, 20, 42);
}
break;
/*case 4: // напряжение аккумулятора для контроля
Refresh = true; // Обновить отрисовку каждый цикл
myGLCD.clrScr(); // Очистка экрана
myGLCD.setFont(SmallFont); // Установка набора символов
myGLCD.print("Bat:", LEFT, 15);
myGLCD.printNumF(analogRead(batPin)/176.6, 2, 24, 15); //напр.батареи (коэфф. подобрать при желании)
break; */
}
if (Refresh) {myGLCD.update(); Refresh = false;} // Вывод вместимого буфера на дисплей и сброс признака обновления
} // if (Lcd_On)
#if defined (debug)
#else
} // скобка для условия сна в начале цикла в отладке не спим
#endif
attachInterrupt(0, wakeUp, LOW); // Проснемся от кнопки
// Отключить питание на 4с
#if defined (debug)
LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF);
#else
LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF);
#endif
if (!key_pressed) {tik++;} else {key_pressed = false; Son_count = 0;} // в зачёт 4с. если не тыкали кнопку
#if defined (debug)
if (tik >=1) {Count_Minute++; Son_count++; tik = 0;} // минута натикала
#else
if (tik >=15) {Count_Minute++; Son_count++; tik = 0;} // минута натикала
#endif
} // Конец цикла
void wakeUp() // прерывание сна по нажатию кнопки
{ // Just a handler for the pin interrupt.
if (!in_int){
in_int = true;
detachInterrupt(0);
if (light_on > 0) {scr_num++;} // Первый тычок только подсвет
light_on = 2; // после нажатия на кнопку подсветка 2*4 = 8с.
Refresh = true; // Обновить отрисовку
key_pressed = true; // кнопку жали
if (scr_num > 3) { // цифра = количество окон (case 1, case 2, case 3)
scr_num = 0;
}
LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); //задержка антидребезга
attachInterrupt(0, wakeUp, LOW); // восстановить прерывания от кнопки
in_int = false;
}
}
Сторінки 1