Всем доброго времени суток. Сегодня включил инет за 2 месяца первый раз и увидел отчет, переезд Ардуино на новый сервер – с новосельицем. Решил тоже предложить свой вклад в это дело своей свистулькой. Все что я задумывал реализовал: уменьшил потребление до 20мА с включенной подсветкой (без нее 14мА) – уменьшил рабочую частоту до 24мГц, питание STMдо 2,65 В. При емкости Акк 3800мА/ч хватает на 7-8 суток при условии: индикация активна только ночью. Решил вопрос с зарядкой – контролируя напряжение на Акк во время заряда и его отключение по достижении заданного напряжения и включения зарядки при падении напряжения до заданного уровня. Все это можно менять в программе. Это дало возможность продлить жизнь Акк. питать изделие от сети, (по возможности) через источник на контроллере Tny264, небольшим током 100-150мА. Он изначально создан работать день и ночь. Применил ЖК технологии IPS, это позволило улучшить контрастность на порядок и больше, угол обзора увеличился фантастически. Это позволило слегка подкрасить голубым циферблат круга, повеселей смотреться стало. Изменил положение экрана с 0 на 3. Улучшилась четкость прорисовки круга, диоды подсветки стоят со стороны шлейфа. В оригинале круг также был со стороны шлейфа, и это было не очень красиво, (положение 2) но экономически верно. Пока выкладываю только фото свистульки и скетч. Если будет интересно, выложу схему попозже к осени, дача все время отнимает. Хотя электронщику и по скетчу многое понятно. В качестве ключа отключающего минусовой провод зарядки от земли, использовал сборку 8205, 2шт в параллель, кварц 4мГц. В качестве источника питания применил любимую 63000, верхнее плечо делителя (ADJ) установить резистор 43кОм, нижнюю часть блочка, сточить до глины 01мкФ. Датчик положения свистульки, контролируется каждые 15 сек. и ВКЛ/ОТКЛ подсветку. А замер напряжения на Акк, происходит раз в минуту, и соответствующее действие. Цвета показаний напряжения: голубой - Акк заряжен, желтый - режим заряда подключен, оранжевый - во избежание выключения Акк, необходимо принять меры к зарядке. Часы при этом не остановятся, просто исчезнет подсветка.
// Библиотека Arduino_STM32-master.zip
#include <Wire.h>
#include <uRTCLib.h> //https://github.com/Naguissa/uRTCLib.git
#include <Adafruit_GFX_AS.h>
#include <Adafruit_ILI9341_STM.h> //_STM
#include <SPI.h>
uRTCLib rtc(0x68);
Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(PA1, PA2, PA3); //cs, dc, rst, Mosi - PA7, SCK, - PA5
float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;
float sdeg = 0, mdeg = 0, hdeg = 0;
uint16_t osx = 120, osy = 120, omx = 120, omy = 120, ohx = 120, ohy = 120;
uint16_t x00 = 0, x11 = 0, y00 = 0, y11 = 0;
uint32_t targetTime = 0;
uint32_t hh, mm, ss;
uint8_t Week;
boolean initial = 1, www = 1, vvv = 1;
void setup(void)
{
Serial.begin(4800);
Wire.begin();
// rtc.set(15, 22, 19, 5, 19, 3, 25);
// uRTCLib::set(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
tft.begin();
tft.setRotation(3); // расположение экрана
tft.fillScreen(ILI9341_WHITE); //стирание всего экрана
tft.drawRect (0, 0, 320, 240, 0x39e7); // прямоугольник
tft.fillCircle(120, 120, 116, 0xb4b4); //круг
tft.fillCircle(120, 120, 114, 0xff78); //стирание внутри круга
pinMode(PA6, INPUT_ANALOG); //выбираем канал АЦП6
GPIOB->regs->CRH = 0x6600; //PB11,PB10,CNF[1:0]= 01-вых.с откр.исток.MODE[1:0]= 10, f-инхр.порта 2Мгц.
GPIOB->regs->ODR |= (1 << 11); // ВКЛючить Акк уст.лог.1(n-chan)
GPIOB->regs->ODR &= ~(1 << 10); //лог.0 на вых.PB10-ВКЛ подсветки(P-chan)
GPIOC->regs->CRH = (0x800000); // Pc13 CNF[1:0]= 10,MODE[1:0]= 00
GPIOC->regs->ODR |= (1 << 13); // с подтяжкой к +
// минуты черточки
for (int i = 0; i < 360; i += 30)
{
sx = cos((i - 90) * 0.0174532925);
sy = sin((i - 90) * 0.0174532925);
x00 = sx * 113 + 120;
y00 = sy * 113 + 120;
x11 = sx * 100 + 120;
y11 = sy * 100 + 120;
tft.drawLine(x00, y00, x11, y11, ILI9341_BLACK); //
}
// секунды точки
for (int i = 0; i < 360; i += 6)
{
sx = cos((i - 90) * 0.0174532925);
sy = sin((i - 90) * 0.0174532925);
x00 = sx * 102 + 120;
y00 = sy * 102 + 120;
// Draw minute markers
tft.drawPixel(x00, y00, ILI9341_BLACK); //
}
//tft.setTextColor(0xcdcd);
tft.setTextColor(ILI9341_NAVY);
tft.drawCentreString("XII", 120, 25, 2);
tft.drawCentreString("IX", 32, 112, 2);
tft.drawCentreString("VI", 122, 200, 2);
tft.drawCentreString("III", 210, 112, 2);
tft.fillCircle(120, 121, 3, ILI9341_BLACK);
targetTime = millis() + 498;
}
void loop()
{
rtc.refresh(); // включить загрузку с rtc
if (targetTime < millis())
{
hh = rtc.hour(); // грузим из rtc в рег-ы
mm = rtc.minute();
ss = rtc.second();
Week = rtc.dayOfWeek();
tft.setTextColor(ILI9341_BLACK);
targetTime = millis() + 498; //заполнение секунды
ss++;
if (ss == 60)
{
ss = 0;
mm++;
if (mm > 59)
{
mm = 0;
hh++;
if (hh > 23)
{
hh = 0;
Week++;
}
}
}
sdeg = ss * 6;
mdeg = mm * 6 + sdeg * 0.01666667;
hdeg = hh * 30 + mdeg * 0.0833333;
hx = cos((hdeg - 90) * 0.0174532925);
hy = sin((hdeg - 90) * 0.0174532925);
mx = cos((mdeg - 90) * 0.0174532925);
my = sin((mdeg - 90) * 0.0174532925);
sx = cos((sdeg - 90) * 0.0174532925);
sy = sin((sdeg - 90) * 0.0174532925);
if (ss == 0 || initial)
{
initial = 0;
tft.drawLine(ohx, ohy, 120, 121, 0xff78); //стирание старых показаний графики
ohx = hx * 62 + 121;
ohy = hy * 62 + 121;
tft.drawLine(omx, omy, 120, 121, 0xff78); //стирание циферблата
omx = mx * 84 + 120;
omy = my * 84 + 120;
}
tft.drawLine(osx, osy, 120, 120, 0xff78); //стирание старых показаний графики
osx = sx * 90 + 120;
osy = sy * 90 + 120;
tft.drawLine(osx, osy, 120, 120, ILI9341_CYAN); //вывод новых оказаний графики
tft.drawLine(ohx, ohy, 120, 121, ILI9341_BLACK);
tft.drawLine(omx, omy, 120, 121, ILI9341_BLACK);
tft.drawLine(osx, osy, 120, 120, ILI9341_CYAN);
tft.fillCircle(120, 121, 3, ILI9341_CYAN);
if (ss == 0 || www == 1) //каждую минуту
{
www = 0;
tft.fillRect(245, 55, 30, 140, ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK); //?
tft.drawNumber(hh / 10, 245, 55, 4);
tft.drawNumber(hh % 10, 260, 55, 4);
tft.drawCentreString(":", 260, 84, 4);
tft.drawNumber(mm / 10, 245, 113, 4);
tft.drawNumber(mm % 10, 260, 113, 4);
tft.drawCentreString(":", 260, 142, 4);
tft.fillRect(288, 55, 30, 140, ILI9341_WHITE); //
tft.setTextColor(ILI9341_BLACK); //?
tft.drawNumber(rtc.day() / 10, 288, 55, 4);
tft.drawNumber(rtc.day() % 10, 304, 55, 4);
tft.drawCentreString("/", 304, 84, 4);
tft.drawNumber(rtc.month() / 10, 288, 113, 4);
tft.drawNumber(rtc.month() % 10, 304, 113, 4);
tft.drawCentreString("/", 304, 142, 4);
// tft.fillRect(150, 280, 30, 25, ILI9341_BLACK);
tft.drawNumber(rtc.year() / 10, 288, 173, 4);
tft.drawNumber(rtc.year() % 10, 304, 173, 4);
tft.fillRect(1, 220, 40, 19, ILI9341_WHITE); //
tft.drawNumber(rtc.temp() / 100, 6, 220, 2); ///
tft.drawCentreString(" C", 25, 219, 2); //
int value = 0; //
value = analogRead(PA6); //читаем данные АЦП
float val = value * (5.50 / 4095.00); //
// tft.fillRect( 0, 3, 45, 19, ILI9341_WHITE); //clear место на экране
if (val > 3.65) tft.setTextColor(ILI9341_RED); //по необходимости
else if (val < 3.65 && val > 3.56) tft.setTextColor(ILI9341_NAVY); //
else if (val < 3.56) tft.setTextColor(ILI9341_DARKCYAN); //
char c1[] = { 0 }; //создаем масив
dtostrf(val, 5, 2, c1); //конвертируем float -> char
tft.fillRect( 1, 3, 45, 19, ILI9341_WHITE); //clear место на экране
tft.drawCentreString( c1, 5, 3, 2); // выводим
tft.drawCentreString("V", 39, 3, 2); //
if (val > 4.18) (GPIOB->regs->ODR &= ~(1 << 11)) ; //ВЫКЛючить заряд Акк- заряжен ~80%.
else if (val < 3.62) (GPIOB->regs->ODR |= (1 << 11)); //ВКЛючить возможность заряда Акк
}
if (hh == 0 && mm == 0 && ss < 2 || vvv == 1) // каждые сутки
{
vvv = 0;
tft.fillRect(253, 10, 55, 25, ILI9341_WHITE);
if (Week > 7) Week = 1;
switch (Week)
{
case 1:
tft.setTextColor(ILI9341_BLACK); //белый
tft.drawCentreString("Mon", 280, 12, 4); break;
case 2:
tft.setTextColor(ILI9341_BLACK);
tft.drawCentreString("Tue", 280, 12, 4); break;
case 3:
tft.setTextColor(ILI9341_BLACK);
tft.drawCentreString("Wed", 280, 12, 4); break;
case 4:
tft.setTextColor(ILI9341_BLACK);
tft.drawCentreString("Thu", 280, 12, 4); break;
case 5:
tft.setTextColor(ILI9341_BLACK);
tft.drawCentreString("Fri", 280, 12, 4); break;
case 6:
tft.setTextColor(ILI9341_RED); //голубой
tft.drawCentreString("Sat", 280, 12, 4); break;
case 7:
tft.setTextColor(ILI9341_DARKCYAN ); //рыжий
tft.drawCentreString("Sun", 280, 12, 4); break;
}
}
tft.fillRect(245, 170, 30, 25, ILI9341_WHITE); //sec
tft.drawNumber(ss / 10, 245, 173, 4);
tft.drawNumber(ss % 10, 260, 173, 4);
tft.setTextColor(ILI9341_NAVY); //восстанов римских
switch (ss)
{
case 16:
tft.drawCentreString("III", 210, 112, 2);
LEDPower(); break;
case 31:
tft.drawCentreString("VI", 122, 200, 2);
LEDPower(); break;
case 46:
tft.drawCentreString("IX", 32, 112, 2);
LEDPower(); break;
case 1:
tft.drawCentreString("XII", 120, 25, 2);
LEDPower(); break;
}
}
// asm("wfi"); //остановка Loop
}
void LEDPower()
{
if ((GPIOC->regs->IDR &(1 << 13)) == 0) //{счит. уровня с рег.датчика
GPIOB->regs->ODR &= ~(1 << 10); // ВКЛ подсветка if PC13= 0
else GPIOB->regs->ODR |= (1 << 10); //{=1 ВЫКЛ подсветка if PC13=1
}


