Red-green matrix information panel with real time clock
-
More than a year ago I created this panel based on the RG 32x16 matrix from sureelectronics.
I've posted a local article about it, google translation is here https://translate.google.com/translate?sl=ru&tl=en&js=y&prev=_t&hl=ru&ie=UTF-8&u=http%3A%2F%2Fradiokot.ru%2Fcircuit%2Fdigital%2Fhome%2F194%2F&edit-text=Just got time last night to migrate it from Plain C + MySensors 1.2 to Arduino + MySensors 1.4.1
It was a bit trickier. I had to create a configuration of arduino based on atmega128. I used a way described here http://download.chip45.com/chip45-arduino-extension.zip (http://www.chip45.com/products/crumbuino-128_arduino_compatible_atmega128_module_board_usb.php)The C code was adjusted to C++. I keep usign C based libraries for RTC, BMP85 and for the matrix.
Schematic is here http://radiokot.ru/circuit/digital/home/194/01.jpg and here http://radiokot.ru/circuit/digital/home/194/02.jpg
Clock creates 3 child devices on controller side:
Controller is updated with preassure, temperature, light level and RTC battery status
This Lua is used to push Street temperature from vera to the Clock:
local temp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1","CurrentTemperature", 61) temp = temp*10.0 luup.call_action("urn:upnp-arduino-cc:serviceId:arduino1", "SendCommand", {radioId="1;255", variableId="VAR_5", value=temp}, 430)
61 is vera ID of wheather plugin current temperature device
430 is Clock node vera device ID
Similar Lua is used to populate Clock with average home temperature:local temp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1","CurrentTemperature", 384) temp = temp*10.0 luup.call_action("urn:upnp-arduino-cc:serviceId:arduino1", "SendCommand", {radioId="1;255", variableId="VAR_4", value=temp}, 430)
384 is vera ID of temperature average device
you can also use VAR_1 to show a short text message on the panel
VAR_2 is reserved to populate a numeric ID to third party connected to Serial1. I plan to setup a voice talking device. ID will call ID.wav or ID.mp3 file to playA short video is here
http://www.youtube.com/watch?v=YOuO6zLDz6UMy hardware kept without changes but it was a challenge to download arduino sketch because I use JTAG. The solution was found with Visualmicro and Atmelstudio. I setup an arduino sketch inside VisulMicro and a separate project for debug of the object file inside atmelStudio,. This allows me not only to upload using the JTAG but also to run a hardware debugging
-
full project is here p6008-rg-matrix-clock.zip
sketch is here:
/* ------------------------------------------------------------------------------------- * user configuration *-------------------------------------------------------------------------------------*/ //#define F_CPU 16000000UL #define TIMERS_BMP085_UPDATE_SEC 10 #define TIMERS_BATTERY_UPDATE_MIN 120 #define TIMERS_VERA_PRESSURE_UPDATE_MINUTE 5 #define TIMERS_VERA_TEMPERATURE_UPDATE_MINUTE 2 #define TIMERS_VERA_BATTERY_UPDATE_MINUTE 120 #define TIMERS_VERA_LIGHT_UPDATE_SECONDS 240 #define TIMERS_VERA_CLOCK_UPDATE_HOUR 12 #define TIMERS_VERA_STREET_TEMPERATURE_MINUTE 60 // minutes, time for street temperature recieved from vera to be timed out #define TIMERS_VERA_FAILED_RADIO_MIN 5 #define rus_str_startup "RG Matrix Clock v1.0" #define rus_str_v_komnate "Local" #define rus_str_v_kvartire "Inside" #define rus_str_na_ulitce "Outside" #define rus_str_davlenie "Preassure" /* ------------------------------------------------------------------------------------- * hardware configuration *-------------------------------------------------------------------------------------*/ #define LED_PORT PORTC #define LED_DATA 3 #define LED_WR 2 #define LED_CLK 1 #define LED_CS 0 #define BUZZER_PORT_OUT PORTE #define BUZZER_PORT_DDR DDRE #define BUZZER_PORT_IN PINE #define BUZZER_PORT_PIN (1 << PE2) typedef enum { ADC_LIGHT=3, ADC_BATTERY=2, ADC_VREF=30 } enum_adc; //#define RF24_NOUART //#define RF24_CE_PORT PORTB //#define RF24_CE_DDR DDRB //#define RF24_CE_PIN PB4 //#define RF24_CSN_PORT PORTB //#define RF24_CSN_DDR DDRB //#define RF24_CSN_PIN PB5 //#define MAX_PAYLOAD_SIZE 32 #define RF_CE 12 #define RF_CSN 13 //#define BMP085_EOC_PORT PINC #define BMP085_EOC_PIN (1 << PINC0) /* ------------------------------------------------------------------------------------- * includes *-------------------------------------------------------------------------------------*/ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> //#include <util/delay.h> #include <stdio.h> #include <MySensor.h> #include <SPI.h> #include "i2c.h" #include "bmp085.h" #include "ds3231.h" #include "ht1632c_c.h" #include "axlib.h" #include "incMsg.h" //#include "uart_printf.h" /* ------------------------------------------------------------------------------------- * globals *-------------------------------------------------------------------------------------*/ #define STREET_TEMPERATURE_NONE -2500 // value used to indicate that street temperature was not set or timed outed enum { vera_sens_temp=0, vera_sens_pressure, vera_sens_light }; typedef enum { display_startup=0, display_clock, display_clock_date, display_temperature_pressure, display_failed_radio } enum_display; volatile struct { uint8_t second; uint8_t display_sec; uint8_t display_type_sec; uint8_t measure_bmp085_sec; uint16_t measure_battery_sec; uint8_t vera_preassure_min; uint8_t vera_temperature_min; uint8_t vera_battery_min; uint16_t vera_light_sec; uint32_t vera_clock_sec; uint16_t vera_failed_radio_min; uint8_t vera_street_temperature; uint8_t vera_apartment_temperature; } timers; enum { radio_ok=0, radio_failed }; struct { int16_t temperature; uint32_t pressureMM; uint8_t light; uint16_t h_light_min; uint16_t h_light_max; uint8_t battery; uint16_t vref; volatile int16_t street_temperature; volatile int16_t apartment_temperature; uint8_t radio_status; char buff[20]; enum_display cur_display; bmp085_calibration calibration; struct { uint16_t s_pressureMM; int16_t temperature; uint8_t battery; uint8_t light; } vera_last; } var; MySensor gw(RF_CE, RF_CSN); /* ------------------------------------------------------------------------------------- * function definition *-------------------------------------------------------------------------------------*/ void buzzerInit() { BUZZER_PORT_DDR |= BUZZER_PORT_PIN; } uint8_t buzzerCheck() { return BUZZER_PORT_IN & BUZZER_PORT_PIN; } void buzzerOn() { BUZZER_PORT_OUT |= BUZZER_PORT_PIN; } void buzzerOff() { BUZZER_PORT_OUT &= ~ BUZZER_PORT_PIN; } AXLIB_TIMER_BLINK(buzzer, buzzerCheck(), buzzerOn(), buzzerOff()) void init_mcu(); void display_sec(uint8_t what); uint8_t adc(uint8_t what); // 20 times each second ISR(TIMER1_COMPA_vect) { axlib_timer_blink_buzzer_update(); } // once a second ISR(TIMER3_COMPA_vect) { timers.second++; if(timers.second == 60) { timers.second = 0; // timers with minutes counting if(timers.vera_preassure_min) timers.vera_preassure_min--; if(timers.vera_temperature_min) timers.vera_temperature_min--; if(timers.vera_battery_min) timers.vera_battery_min--; if(timers.vera_failed_radio_min && timers.vera_failed_radio_min != 1) timers.vera_failed_radio_min--; if(timers.vera_street_temperature) { if(!--timers.vera_street_temperature) var.street_temperature = STREET_TEMPERATURE_NONE; } if(timers.vera_apartment_temperature) { if(!--timers.vera_apartment_temperature) var.apartment_temperature = STREET_TEMPERATURE_NONE; } } // timers with seconds counting if(timers.measure_bmp085_sec) timers.measure_bmp085_sec--; if(timers.display_sec) timers.display_sec--; if(timers.display_type_sec) timers.display_type_sec--; if(timers.vera_clock_sec) timers.vera_clock_sec--; if(timers.vera_light_sec) timers.vera_light_sec--; // measurement of RTC battery level if(timers.measure_battery_sec) --timers.measure_battery_sec; } ISR(TIMER2_OVF_vect) { } // adc #define ADC_COUNT_AVG 16 #define ADC_BG 30 #define BATTERY_MIN 250 // V*100, 0% #define BATTERY_MAX 300 // V*100, 100% volatile uint16_t adc_count; volatile uint16_t adc_sum; uint8_t adc(uint8_t what) { adc_count = ADC_COUNT_AVG; adc_sum = 0; ADMUX = (0 << REFS1) | (1 << REFS0) | what; ADCSRA |= (1 << ADSC); return 1; } ISR(ADC_vect) { adc_sum += ADCW; if(!--adc_count) { // finished uint8_t channel = ADMUX & 0x1F; switch(channel) { case ADC_LIGHT: { // should be between 0% and 100% // 0% is most dark if(var.h_light_max < adc_sum) var.h_light_max = adc_sum; if(var.h_light_min > adc_sum) var.h_light_min = adc_sum; uint32_t v = adc_sum - var.h_light_min; v *= 100; v /= (var.h_light_max - var.h_light_min); var.light = 100 - v; break; } case ADC_BATTERY: { uint32_t v = adc_sum; v *= var.vref; v /= 1023; v /= ADC_COUNT_AVG; // translate voltage to % //if(v >= BATTERY_MAX) var.battery = 100; //else if(v <= BATTERY_MIN) var.battery = 0; //else { //v -= BATTERY_MIN; //v *= 100; //v /= (BATTERY_MAX - BATTERY_MIN); //} //var.battery = v; var.battery = axlib_convert_volt2percent_lithium_notrechargeable(v); timers.measure_battery_sec = TIMERS_BATTERY_UPDATE_MIN * 60; break; } case ADC_BG: { uint32_t v = 131; // should be 123 (1.23V) but this one is corrected v *= 1023; v /= adc_sum; v *= 16; var.vref = v; break; } } // find what next to measure if(!timers.measure_battery_sec) channel = ADC_BATTERY; else { switch(channel) { case ADC_LIGHT: channel = ADC_VREF; break; case ADC_VREF: channel = ADC_LIGHT; break; case ADC_BATTERY: channel = ADC_LIGHT; break; } } adc(channel); } else { // next round ADCSRA |= (1 << ADSC); } } /* ------------------------------------------------------------------------------------- * main functions *-------------------------------------------------------------------------------------*/ void setup() { // variables init timers.second = 0; timers.measure_battery_sec = 0; timers.measure_bmp085_sec = 0; timers.vera_preassure_min = 0; timers.vera_clock_sec = 10; timers.vera_light_sec = 0; timers.vera_battery_min = 0; timers.display_sec = 0; timers.vera_failed_radio_min = 0; timers.vera_street_temperature = 0; timers.vera_apartment_temperature = 0; var.vref = 500; var.radio_status = radio_ok; var.street_temperature = STREET_TEMPERATURE_NONE; var.apartment_temperature = STREET_TEMPERATURE_NONE; init_mcu(); buzzerInit(); axlib_timer_blink_buzzer_init(); // init uart printing Serial.begin(115200); Serial1.begin(9600); //uart_debug_init(UART_PRINTF_BAUDRATE(115200, F_CPU)); //uart_debugf_1_P(PSTR("\n------------------------------\nRG Matrix clock started v1.0\n")); gw.debugPrint(PSTR("\n------------------------------\nRG Matrix clock started v1.0\n")); // init bmp085 i2cInit(); bmp085_readCalibration(&var.calibration); gw.debugPrint(PSTR("\n1. BMP085 calibration data:\n")); gw.debugPrint(PSTR("- ac1 = %i\n"), var.calibration.ac1); gw.debugPrint(PSTR("- ac2 = %i\n"), var.calibration.ac2); gw.debugPrint(PSTR("- ac3 = %i\n"), var.calibration.ac3); gw.debugPrint(PSTR("- ac4 = %i\n"), var.calibration.ac4); gw.debugPrint(PSTR("- ac5 = %i\n"), var.calibration.ac5); gw.debugPrint(PSTR("- ac6 = %i\n"), var.calibration.ac6); gw.debugPrint(PSTR("- b1 = %i\n"), var.calibration.b1); gw.debugPrint(PSTR("- b2 = %i\n"), var.calibration.b2); gw.debugPrint(PSTR("- mb = %i\n"), var.calibration.mb); gw.debugPrint(PSTR("- mc = %i\n"), var.calibration.mc); gw.debugPrint(PSTR("- md = %i\n\n"), var.calibration.md); // set 24 hour format of RTC DS3231Set24(1); gw.debugPrint(PSTR("2. DS3231 init done\n")); // init rg matrix //uart_debugf_1_P(PSTR("3. LED init\n")); gw.debugPrint(PSTR("3. LED init\n")); ht1632c_init(&LED_PORT, LED_DATA, LED_WR, LED_CLK, LED_CS, HT1632_COLOR_GEOM_32x16, 1); ht1632c_pwm(15); // vera init //uart_debugf_1_P(PSTR("4. Vera inititalization started\n")); Serial.println("4. Vera initialization started\n"); gw.begin(incomingMessage); gw.sendSketchInfo("RG Matrix clock", "2.0"); gw.present(vera_sens_temp, S_TEMP); gw.present(vera_sens_pressure, S_BARO); gw.present(vera_sens_light, S_LIGHT_LEVEL); //VeraSensor_sendSensorPresentation(vera_sens_temp, S_TEMP); //VeraSensor_sendSensorPresentation(vera_sens_pressure, S_BARO); //VeraSensor_sendSensorPresentation(vera_sens_light, S_LIGHT_LEVEL); //uart_debugf_2_P(PSTR("- radioId = %i\n"), gw.getNodeId()); axlib_timer_blink_buzzer_run(1, 1); //wdt_enable(WDTO_2S); //uart_debugf_1_P(PSTR("5. WDT init done\n\n")); //uart_debugf_1_P(PSTR("------------------------------\nMain loop initiated\n\n")); gw.debugPrint(PSTR("------------------------------\nMain loop initiated\n")); sei(); var.cur_display = display_startup; timers.display_type_sec = 0; adc(ADC_VREF); } void loop() { gw.process(); // request clock synchronization if needed if(!timers.vera_clock_sec) { //uart_debugf_1_P(PSTR("- requested clock sync from vera\n")); gw.debugPrint(PSTR("- requested clock sync from vera\n")); gw.requestTime(receiveTime); timers.vera_clock_sec = 30; if(!timers.vera_failed_radio_min) timers.vera_failed_radio_min = TIMERS_VERA_FAILED_RADIO_MIN; } // it is a time to update measurement on bmp085 if(!timers.measure_bmp085_sec) { int32_t pressure; bmp085_get(&var.calibration, BMP085_OSS_ULTRAHIGHRESOLUTION, &var.temperature, &pressure); var.pressureMM = bmp085_convertPAtoMM(pressure); gw.debugPrint(PSTR("- updated temperature %i.%i, pressure %li.%li mm\n"), var.temperature/10, var.temperature % 10, var.pressureMM/1000, var.pressureMM%1000); // check if update on pressure to vera is needed if(!timers.vera_preassure_min) { // update vera on pressure only that often // use for vera only one digit after dot, rounded uint16_t s_pressureMM = (var.pressureMM + 50) / 100; if(var.vera_last.s_pressureMM != s_pressureMM) { // do an update to vera sprintf_P(var.buff, PSTR("%i.%d"), s_pressureMM / 10, (int)(s_pressureMM % 10)); gw.debugPrint(PSTR("- sending update to Vera pressureMM = %s\n"), var.buff); MyMessage pressureMsg(vera_sens_pressure, V_PRESSURE); MyMessage forecastMsg(vera_sens_pressure, V_FORECAST); gw.send(pressureMsg.set(var.buff)); gw.send(forecastMsg.set("unknown")); //VeraSensor_sendVariableString(vera_sens_pressure, V_PRESSURE, buff); var.vera_last.s_pressureMM = s_pressureMM; timers.vera_preassure_min = TIMERS_VERA_PRESSURE_UPDATE_MINUTE; } } // check if update on temperature to vera is needed if(!timers.vera_temperature_min || abs(var.vera_last.temperature-var.temperature) > 20) { // update vera on temperature only that often if(var.vera_last.temperature != var.temperature) { // do an update to vera sprintf_P(var.buff, PSTR("%i.%i"), var.temperature / 10, var.temperature % 10); gw.debugPrint(PSTR("- sending update to Vera temperature = %s\n"), var.buff); MyMessage tempMsg(vera_sens_temp, V_TEMP); gw.send(tempMsg.set(var.buff)); //VeraSensor_sendVariableString(vera_sens_temp, V_TEMP, buff); var.vera_last.temperature = var.temperature; timers.vera_temperature_min = TIMERS_VERA_TEMPERATURE_UPDATE_MINUTE; } } timers.measure_bmp085_sec = TIMERS_BMP085_UPDATE_SEC; } // update vera on battery if(!timers.vera_battery_min) { if(var.vera_last.battery != var.battery) { gw.debugPrint(PSTR("- sending update to Vera battery = %d%%\n"), var.battery); gw.sendBatteryLevel(var.battery); var.vera_last.battery = var.battery; timers.vera_battery_min = TIMERS_VERA_BATTERY_UPDATE_MINUTE; } } // update vera on light if(!timers.vera_light_sec || abs(var.vera_last.light - var.light) > 10) { if(var.vera_last.light != var.light) { gw.debugPrint(PSTR("- sending update to Vera light = %d%%\n"), var.light); MyMessage msg(vera_sens_light, V_LIGHT_LEVEL); gw.send(msg.set(var.light)); var.vera_last.light = var.light; timers.vera_light_sec = TIMERS_VERA_LIGHT_UPDATE_SECONDS; } } if(timers.vera_failed_radio_min == 1) { timers.vera_failed_radio_min = TIMERS_VERA_FAILED_RADIO_MIN; var.cur_display = display_failed_radio; var.radio_status = radio_failed; } if(!timers.display_sec) { display_sec(var.cur_display); timers.display_sec = 1; } if(!timers.display_type_sec) { switch(var.cur_display) { case display_startup: case display_failed_radio: case display_temperature_pressure: var.cur_display = display_clock; timers.display_type_sec = 10; //ht1632c_clear(); break; case display_clock: var.cur_display = display_clock_date; timers.display_type_sec = 6; //ht1632c_clear(); break; case display_clock_date: var.cur_display = display_temperature_pressure; timers.display_type_sec = 6; //ht1632c_clear(); break; } } wdt_reset(); } /* ------------------------------------------------------------------------------------- * internal function *-------------------------------------------------------------------------------------*/ // This is called when a new time value was received void receiveTime(unsigned long time) { uint8_t hour, minute, second; uint8_t month, day; uint16_t year; axlib_time_convert(time, &hour, &minute, &second); axlib_date_convert(time, &day, &month, &year); gw.debugPrint(PSTR("- new time recieved %02d:%02d.%02d\n"), hour, minute, second); gw.debugPrint(PSTR("- new date recieved %02d.%02d.%04d\n"), day, month, year); DS3231SetFullTime24(hour, minute, second); DS3231SetFullDate(year, month, day, 1); timers.vera_clock_sec = TIMERS_VERA_CLOCK_UPDATE_HOUR * 3600UL; } void setStreetTemp(int t) { // getting street temperature var.street_temperature = t; gw.debugPrint(PSTR("- street temperature received %d\n"), var.street_temperature); // stupid validity check if(var.street_temperature > -600 && var.street_temperature < 1000) timers.vera_street_temperature = TIMERS_VERA_STREET_TEMPERATURE_MINUTE; else var.street_temperature = STREET_TEMPERATURE_NONE; } void setRoomTemp(int t) { // getting apartment temperature var.apartment_temperature = t; gw.debugPrint(PSTR("- apartment temperature received %d\n"), var.apartment_temperature); // stupid validity check if(var.apartment_temperature > -600 && var.apartment_temperature < 1000) timers.vera_apartment_temperature = TIMERS_VERA_STREET_TEMPERATURE_MINUTE; else var.apartment_temperature = STREET_TEMPERATURE_NONE; } void setTextToShow(char* str) { // text message received ht1632c_setfont(FONT_8x13BK); ht1632c_animate_hscrolltext(1, str, HT1632_COLOR_GREEN, 20, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 8); } void setSoundID(int id) { Serial1.println(id); } void clearRadioStatus() { timers.vera_failed_radio_min = 0; var.radio_status = radio_ok; ht1632c_animate_rect_fillfrominside(10, 5, HT1632_COLOR_RED, 5); ht1632c_animate_rect_fillfrominside(17, 10, HT1632_COLOR_GREEN, 5); ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_BLACK, 5); for(uint8_t i=0; i<3; i++) { ht1632c_setfont(FONT_5x7W); ht1632c_rect(8, 2, 23, 13, HT1632_COLOR_ORANGE); ht1632c_putstr(10, 4, "IN", HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK); ht1632c_sendframe(); wdt_reset(); _delay_ms(100); ht1632c_clear(); ht1632c_sendframe(); wdt_reset(); _delay_ms(100); wdt_reset(); } } void display_temperature(int16_t temperature, uint8_t color, uint8_t bg_color) { uint8_t neg = (temperature<0)?1:0; if(neg) temperature = -temperature; uint8_t dig1 = temperature / 100; uint8_t dig2 = (temperature / 10) % 10; uint8_t dig3 = temperature % 10; uint8_t x = (dig1)?0:7; if(!dig3) x += 4; ht1632c_setfont(FONT_8x13BK); if(neg) { temperature = - temperature; ht1632c_rect(x, 7, x+2, 8, color); x += (dig1)?3:4; } else { x += 1; } ht1632c_setfont(FONT_8x13BK); if(dig1) { // ГЙЖТБ ДЕУСФЛПЧ, ОПМШ РТПРХУЛБЕН ht1632c_putchar(x, 2, dig1 + '0', color, 0, bg_color); x += 8; } // ГЙЖТБ ЕДЙОЙГ, ОПМШ РПЛБЪЩЧБЕН ht1632c_putchar(x, 2, dig2 + '0', color, 0, bg_color); x += 8; if(dig3) { // ДЕУСФЙЮОБС ФПЮЛБ: ПФПВТБЦБЕН ЕУМЙ ЪОБЮБЪБС ГЙЖТБ РПУМЕ ФПЮЛЙ ht1632c_rect(x, 11, x+1, 12, color); x += 3; ht1632c_putchar(x, 2, dig3 + '0', color, 0, bg_color); x += 8; } // ЪОБЛ ЗТБДХУПЧ ht1632c_line(x-1, 0, x-1, 2, color); ht1632c_line(x+1, 0, x+1, 2, color); ht1632c_line(x-1, 0, x+1, 0, color); ht1632c_line(x-1, 2, x+1, 2, color); x += 3; if(x < 31-8) { ht1632c_putchar(x, 2, 'C', color, 0, bg_color); } ht1632c_sendframe(); /* if(var.street_temperature > 0 || (var.street_temperature > -99)) { // display with dot if we have space sprintf_P(buff, PSTR("%d.%d`"), var.street_temperature/10, abs(var.street_temperature)%10); ht1632c_setfont(FONT_6x13); ht1632c_putstr(1, 1, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK); } else { // duisplay without dot if space is limited sprintf_P(buff, PSTR("%d`"), var.street_temperature/10); ht1632c_setfont(FONT_8x13BK); ht1632c_putstr(4, 2, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK); } ht1632c_sendframe(); */ } void display_pressure(uint16_t pressure, uint8_t color, uint8_t bg_color) { uint8_t dig1 = pressure / 100; uint8_t dig2 = (pressure / 10 ) % 10; uint8_t dig3 = pressure % 10; ht1632c_setfont(FONT_8x13BK); ht1632c_putchar(0, 2, dig1+'0', color, 0, bg_color); ht1632c_putchar(8, 2, dig2+'0', color, 0, bg_color); ht1632c_putchar(16, 2, dig3+'0', color, 0, bg_color); ht1632c_setfont(FONT_4x6); ht1632c_putchar(24, 8, 'm', color, 0, bg_color); ht1632c_putchar(28, 8, 'm', color, 0, bg_color); ht1632c_sendframe(); } void display_clockf(int8_t x, int8_t y, uint8_t color, uint8_t bg_color) { uint8_t a, b, c; ht1632c_setfont(FONT_6x13B); DS3231GetFullTime24(&a, &b, &c); x += ht1632c_putchar(x, y, '0'+a/10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); x += ht1632c_putchar(x, y, '0'+a%10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); if(c%2) { ht1632c_rect(x, y+3, x+1, y+3+2, HT1632_COLOR_ORANGE); ht1632c_rect(x, y+7, x+1, y+7+2, HT1632_COLOR_ORANGE); } x += 6; x += ht1632c_putchar(x-3, y, '0'+b/10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); ht1632c_putchar(x-3, y, '0'+b%10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); ht1632c_sendframe(); } void display_sec(uint8_t what) { char buff[64]; ht1632c_clear(); switch(what) { case display_clock: display_clockf(1, 1, HT1632_COLOR_ORANGE, HT1632_COLOR_BLACK); break; case display_clock_date: { uint8_t a, b, c, d; ht1632c_setfont(FONT_5x7W); DS3231GetFullTime24(&a, &b, &c); sprintf(buff, "%02d%c%02d", a, (c%2)?':':' ', b); ht1632c_putstr(1, 1, buff, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); DS3231GetFullDate(&a, &b, &c, &d); sprintf(buff, "%02d.%02d", c, b); ht1632c_putstr(1, 9, buff, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); break; } case display_startup: { ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_GREEN, 10); //_delay_ms(500); ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_RED, 10); //_delay_ms(500); ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_ORANGE, 10); //_delay_ms(500); ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_BLACK, 10); ht1632c_setfont(FONT_8x13BK); ht1632c_animate_hscrolltext(1, rus_str_startup, HT1632_COLOR_ORANGE, 20, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16); break; } case display_temperature_pressure: // display street temperature if(var.street_temperature != STREET_TEMPERATURE_NONE) { ht1632c_setfont(FONT_8x13BK); sprintf_P(buff, PSTR(rus_str_na_ulitce)); ht1632c_animate_hscrolltext(1, buff, HT1632_COLOR_RED, 5, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16); /* if(var.street_temperature > 0 || (var.street_temperature > -99)) { // display with dot if we have space sprintf_P(buff, PSTR("%d.%d`"), var.street_temperature/10, abs(var.street_temperature)%10); ht1632c_setfont(FONT_6x13); ht1632c_putstr(1, 1, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK); } else { // duisplay without dot if space is limited sprintf_P(buff, PSTR("%d`"), var.street_temperature/10); ht1632c_setfont(FONT_8x13BK); ht1632c_putstr(4, 2, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK); } ht1632c_sendframe();*/ display_temperature(var.street_temperature, HT1632_COLOR_RED, HT1632_COLOR_BLACK); ht1632c_delay_ms(3000); ht1632c_clear(); } // display room temperature { const void* str; int16_t temp; if(var.apartment_temperature != STREET_TEMPERATURE_NONE) { str = PSTR(rus_str_v_kvartire); temp = var.apartment_temperature; } else { str = PSTR(rus_str_v_komnate); temp = var.temperature; } ht1632c_setfont(FONT_8x13BK); sprintf_P(buff, (const char*)str); ht1632c_animate_hscrolltext(1, buff, HT1632_COLOR_ORANGE, 5, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16); // sprintf_P(buff, PSTR("%d.%d`"), temp/10, temp%10); display_temperature(temp, HT1632_COLOR_ORANGE, HT1632_COLOR_BLACK); ht1632c_delay_ms(3000); ht1632c_clear(); } // ht1632c_setfont(FONT_6x13); //ht1632c_putstr(1, 1, buff, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK); //ht1632c_sendframe(); // display atmosphere preasure ht1632c_setfont(FONT_8x13BK); sprintf_P(buff, PSTR(rus_str_davlenie)); ht1632c_animate_hscrolltext(1, buff, HT1632_COLOR_GREEN, 5, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16); // sprintf(buff, "%dmm", (int)((var.pressureMM+500)/1000)); // ht1632c_setfont(FONT_6x13); // ht1632c_putstr(1, 1, buff, HT1632_COLOR_GREEN, 0, HT1632_COLOR_BLACK); // ht1632c_sendframe(); display_pressure(((var.pressureMM+500)/1000), HT1632_COLOR_GREEN, HT1632_COLOR_BLACK); ht1632c_delay_ms(3000); break; case display_failed_radio: ht1632c_setfont(FONT_8x13BK); //axlib_timer_blink_buzzer_run(3, 1); ht1632c_animate_hscrolltext(1, "Тег йбиум й Vera", HT1632_COLOR_RED, 50, 2, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16); break; } // radio status //ht1632c_rect(30, 0, 31, 1, (var.radio_status==radio_ok)?HT1632_COLOR_GREEN:HT1632_COLOR_RED); ht1632c_plot(31, 0, (var.radio_status==radio_ok)?HT1632_COLOR_GREEN:HT1632_COLOR_RED); ht1632c_sendframe(); } void init_mcu() { // timer 1 - 20 times per second // CTC mode // TCCR1A = (0 << WGM11) | (0 << WGM10); // CTC mode + /64 // TCCR1B = (0 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (1 << CS10); // OCR1A = 9375; // timer2 // clock source - T2 TCCR2 = (1 << CS22) | (1 << CS21) | (1 << CS20); // timer 3 - once a second // CTC mode TCCR3A = (0 << WGM31) | (0 << WGM30); // /256 prescaler + CTC mode TCCR3B = (0 << WGM33) | (1 << WGM32) | (1 << CS32) | (0 << CS31) | (0 << CS30); OCR3A = F_CPU / 256; TIMSK |= (0 << TOIE2);// | (1 << OCIE1A); ETIMSK = (1 << OCIE3A); // adc ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); }
Suggested Topics
-
Welcome
Announcements • • hek