Časove hodiny RTC + GSM
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Časove hodiny RTC + GSM
Dobrý deň,
najprv uvediem aký je zámer. Pomocou Arduino Mega 2560 , DS1307 RTC a modulu SIM900 urobiť časove hodiny ktoré spínajú relé. Ich funkcia by mala byt nasledovná:
- spínať relé podľa času s RTC
- pomocou zavolania zapnúť a vypnúť relé
- raz za mesiac nastaviť RTC čas s GSM modulu
Prikladám aj to čo som zatiaľ napísal. Viem, že to nie je krásne napísané a asi niekto by to napísal lepšie, ale takto je to pre mňa zrozumiteľné a verím že bude funkčné . Pri písaní kódu som ale narazil na problém , ktorý sa mi nedari vyriešiť a preto spolieham na rady skúsenejších.
Ak pustím samotný časovač s čítaním RTC, časovač funguje podľa mojich predstáv a spína relé ako ma na sekundu presne. V tom momente ako som pridal podmienku na čakanie hovoru prestal cely časovač fungovať korektne. Aj na výpise v terminály je vidieť odozva každých <5 sek. Musel som s podmienok času vymazať sekundy. Ak sa to netrafilo do sekúnd tak sa stav relé nezmenil (čo je logické). Zmena stavu pomocou zavolania funguje korektne. Ako dosiahnuť aby čas išiel ako ma, aby som ohol spínať na sekundy?
Mám ešte ďalší problém, ale to je ďalšia časť kde po načítaní času s GSM pomocou AT+CCLK? spôsob ako s toho dostať formát, ktorý by bol použiteľný do príkazu RTC.adjust(DateTime(__DATE__, __TIME__)).
A ešte mám jednu zaujímavosť. Ak k modulu DS1307 pripojím GND pin tak prestane fungovať.
Ďakujem!
najprv uvediem aký je zámer. Pomocou Arduino Mega 2560 , DS1307 RTC a modulu SIM900 urobiť časove hodiny ktoré spínajú relé. Ich funkcia by mala byt nasledovná:
- spínať relé podľa času s RTC
- pomocou zavolania zapnúť a vypnúť relé
- raz za mesiac nastaviť RTC čas s GSM modulu
Prikladám aj to čo som zatiaľ napísal. Viem, že to nie je krásne napísané a asi niekto by to napísal lepšie, ale takto je to pre mňa zrozumiteľné a verím že bude funkčné . Pri písaní kódu som ale narazil na problém , ktorý sa mi nedari vyriešiť a preto spolieham na rady skúsenejších.
Ak pustím samotný časovač s čítaním RTC, časovač funguje podľa mojich predstáv a spína relé ako ma na sekundu presne. V tom momente ako som pridal podmienku na čakanie hovoru prestal cely časovač fungovať korektne. Aj na výpise v terminály je vidieť odozva každých <5 sek. Musel som s podmienok času vymazať sekundy. Ak sa to netrafilo do sekúnd tak sa stav relé nezmenil (čo je logické). Zmena stavu pomocou zavolania funguje korektne. Ako dosiahnuť aby čas išiel ako ma, aby som ohol spínať na sekundy?
Mám ešte ďalší problém, ale to je ďalšia časť kde po načítaní času s GSM pomocou AT+CCLK? spôsob ako s toho dostať formát, ktorý by bol použiteľný do príkazu RTC.adjust(DateTime(__DATE__, __TIME__)).
A ešte mám jednu zaujímavosť. Ak k modulu DS1307 pripojím GND pin tak prestane fungovať.
Ďakujem!
- Přílohy
-
- CAS_CALL.ino
- (5.71 KiB) Staženo 304 x
Re: Časove hodiny RTC + GSM
Dobrý den, zkusím nadhodit pár myšlenek, třeba některé budou užitečné 
Nesprávné časování
Problém
Jestli dobře chápu popis problému, tak část, která kód zdržuje je:
Zkuste napsat samostatný program, ve kterém vypíšete přes sériovou linku čas (millis()) před a po zavolání funkce sim900.isCallActive(telCislo). Uvidíte, jak dlouho provádění této funkce přibližně trvá.
Podle mě totiž tato funkce na delší dobu "zdrží" procesor. Proto ten výpadek cca 5s.
Řešení 1
Napadají mě dvě řešení. První z nich je upravit kód tak, aby mu toto zdržení nevadilo. Nevím, jestli je kód kritický natolik, že 5s zdržení vadí. Pokud ne, mohlo by toto být řešení.
Problém je asi způsob testování času:
Zde je problém v tom, že když se program netrefí do konkrétní minuty, nedojde k sepnutí/vypnutí.
Navrhuji si čas převést něco na způsob zjednodušeného timestamp. To bude udávat počet vteřin, které uběhly od začátku dne (00:00) ve vteřinách.
pokud byste chtěl ještě přidat vteřiny, můžete řádek upravit na
Pokud dobře koukám do kódu, tak každý den v 16:30 relé zapínáte a 8:30 vypínáte.
Nemusíte mít podmínku pro každý den, ale jen pro konkrétní časy - slovy: "když je více než 16:30 a je relé vypnuto, zapni ho" a "když je více než 8:30 a je relé zapnuto, vypni ho". Když to přepíšeme do kódu, tak:
To by mělo vyřešit problém způsobený zpožděním.
Řešení 2
Druhou možností, která mě napadá je využít přerušení. Jestli se nepletu, tak některé RTC moduly mají vyhrazený pin, na kterém každou vteřinu vyšlou pulz. Na tento pulz by mohlo Arduino reagovat pomocí přerušení a zkontrolovat aktuální čas. Do tohoto řešení bych se ale nepouštěl, pokud bude Řešení 1 dostačující
Převod formátu data
Na převod dat z formátu do formátu vás odkáži na dvě funkce sscanf (http://www.cplusplus.com/reference/cstdio/sscanf/) a sprintf(http://www.cplusplus.com/reference/cstdio/sprintf/).
Pomocí sscanf načtete data z řetězce získaného z AT+CCLK? do proměnných a ty pak dosadíte do správného tvaru funkcí sprintf.

Nesprávné časování
Problém
Jestli dobře chápu popis problému, tak část, která kód zdržuje je:
Kód: Vybrat vše
if(sim900.isCallActive(telCislo)) {
Podle mě totiž tato funkce na delší dobu "zdrží" procesor. Proto ten výpadek cca 5s.
Řešení 1
Napadají mě dvě řešení. První z nich je upravit kód tak, aby mu toto zdržení nevadilo. Nevím, jestli je kód kritický natolik, že 5s zdržení vadí. Pokud ne, mohlo by toto být řešení.
Problém je asi způsob testování času:
Kód: Vybrat vše
if (now.hour() == 16 && now.minute() == 30 && now.dayOfTheWeek() == 1 )
Navrhuji si čas převést něco na způsob zjednodušeného timestamp. To bude udávat počet vteřin, které uběhly od začátku dne (00:00) ve vteřinách.
Kód: Vybrat vše
unsigned long time = now.hour() * 60 * 60 + now.minute() * 60;
Kód: Vybrat vše
unsigned long time = now.hour() * 60 * 60 + now.minute() * 60 + now.second();
Nemusíte mít podmínku pro každý den, ale jen pro konkrétní časy - slovy: "když je více než 16:30 a je relé vypnuto, zapni ho" a "když je více než 8:30 a je relé zapnuto, vypni ho". Když to přepíšeme do kódu, tak:
Kód: Vybrat vše
unsigned long time8_30 = 8 * 60 * 60 + 30 * 60;
unsigned long time16_30 = 16 * 60 * 60 + 30 * 60;
if(time >= time16_30 && StatusRelay == 0){
Serial.print(" Start ");
StatusRelay = 1;
}
else if(time >= time8_30 && StatusRelay == 1){
Serial.print(" Stop ");
StatusRelay = 0;
}
Řešení 2
Druhou možností, která mě napadá je využít přerušení. Jestli se nepletu, tak některé RTC moduly mají vyhrazený pin, na kterém každou vteřinu vyšlou pulz. Na tento pulz by mohlo Arduino reagovat pomocí přerušení a zkontrolovat aktuální čas. Do tohoto řešení bych se ale nepouštěl, pokud bude Řešení 1 dostačující

Převod formátu data
Na převod dat z formátu do formátu vás odkáži na dvě funkce sscanf (http://www.cplusplus.com/reference/cstdio/sscanf/) a sprintf(http://www.cplusplus.com/reference/cstdio/sprintf/).
Pomocí sscanf načtete data z řetězce získaného z AT+CCLK? do proměnných a ty pak dosadíte do správného tvaru funkcí sprintf.
Re: Časove hodiny RTC + GSM
Dobrý deň,
ďakujem za myšlienky a rozšírenie obzoru!
Áno, v tejto podmienke sa to asi niekde zastaví/spomalí.
Nie že by 5 sekúnd bol problém, ale zaujíma ma to z princípu prečo to je tak.
Kvôli tomu som upravil kód tak, aby sekundy nebral do úvahy. Nie som žiaden programátor, ale skúsim zmerať ten čas.
Dôvodom prečo sú všade aj dni ten, že 4 krát sa to spúšťa o 16.30 a vypne o 8.30, ale 1 krat sa to zapne 16.30 a vypne o 8.30 avšak o 2 dni (beží to kontinuálne od piatka poobedia až do pondelka rana). Ak by to bolo pravidelne tiež by som to riešil len jednou podmienkou. Skúsim implementovať funkciu či sa niečo zmení.
Ďakujem za funkcie. Skúsim ich použiť, ale zatiaľ som nedostal z AT+CCLK? výstup do premennej ktorú by som rozložil.
ďakujem za myšlienky a rozšírenie obzoru!
Áno, v tejto podmienke sa to asi niekde zastaví/spomalí.
Kód: Vybrat vše
if(sim900.isCallActive(telCislo)) {
Kvôli tomu som upravil kód tak, aby sekundy nebral do úvahy. Nie som žiaden programátor, ale skúsim zmerať ten čas.
Dôvodom prečo sú všade aj dni ten, že 4 krát sa to spúšťa o 16.30 a vypne o 8.30, ale 1 krat sa to zapne 16.30 a vypne o 8.30 avšak o 2 dni (beží to kontinuálne od piatka poobedia až do pondelka rana). Ak by to bolo pravidelne tiež by som to riešil len jednou podmienkou. Skúsim implementovať funkciu
Kód: Vybrat vše
unsigned long time = now.hour() * 60 * 60 + now.minute() * 60 + now.second();
Ďakujem za funkcie. Skúsim ich použiť, ale zatiaľ som nedostal z AT+CCLK? výstup do premennej ktorú by som rozložil.
Re: Časove hodiny RTC + GSM
Dobrý den,
provedení různých funkcí trvá různě dlouho. Záleží na tom, jak je funkce komplexní a jak moc časově náročné věci vykonává. Když třeba vytvoříme funkci
tak bude trvat cca 5s a to vlastně nic nedělá.
V sim900.isCallActive(telCislo) je tedy asi něco, co trvá dlouho (komunikace s modulem, ...). Jistý si ale úplně nejsem.
To měření času může být třeba takovéto:
Pardon, toho přeskočení dvou dní jsem si nevšiml. Můžete to ale udělat podobně, jen do time přidáte ještě dny.
Time je potom počet vteřin od začátku týdne.
Podmínku sestavíte tak, že si vytvoříte timestamp pro jednotlivé časy - třeba pondělí 8:30, pondělí 16:30 atd. A budete je testovat OD NEJVĚTŠÍHO (jinak by podmínka uspěla vždy při pondělním timestamp, i když by byl pátek apod.). Tedy:
K tomu AT+CCLK? - podařilo se vám získat z modulu nějaký čas a jen nevíte, jak se tento čas uloží do proměnné, nebo jen víte, že existuje příkaz AT+CCLK? a nevíte, jak ho použít?
provedení různých funkcí trvá různě dlouho. Záleží na tom, jak je funkce komplexní a jak moc časově náročné věci vykonává. Když třeba vytvoříme funkci
Kód: Vybrat vše
function dlouhaFunkce(){
delay(5000);
}
V sim900.isCallActive(telCislo) je tedy asi něco, co trvá dlouho (komunikace s modulem, ...). Jistý si ale úplně nejsem.
To měření času může být třeba takovéto:
Kód: Vybrat vše
unsigned long before, after;
//zde přidejte vložení knihoven apod.
void setup(){
before = millis();
sim900.isCallActive(telCislo);
after = millis();
Serial.begin(9600);
Serial.print("Before: ");
Serial.println(before);
Serial.print("After: ");
Serial.println(after);
Serial.print("Duration: ");
Serial.println(after - before);
}
void loop(){}
Kód: Vybrat vše
unsigned long time = now.dayOfTheWeek() * 24 * 60 * 60 + now. now.hour() * 60 * 60 + now.minute() * 60 + now.second();
Podmínku sestavíte tak, že si vytvoříte timestamp pro jednotlivé časy - třeba pondělí 8:30, pondělí 16:30 atd. A budete je testovat OD NEJVĚTŠÍHO (jinak by podmínka uspěla vždy při pondělním timestamp, i když by byl pátek apod.). Tedy:
Kód: Vybrat vše
if(time > patek16_30 && StatusRelay == 0){
StatusRelay = 1;
}
else if(time > patek8_30 && StatusRelay == 1){
StatusRelay = 0;
}
else if(time > ctvrtek16_30 && StatusRelay == 0){...}
.
.
.
Re: Časove hodiny RTC + GSM
Dobrý deň,
ešte raz ďakujem za snahu a nasmerovanie.
Mali ste absolútnu pravdu. Váš program vypísal trvanie funkcie presne 5145ms.
Potom som pozeral do súboru sim900.h kde je hneď na začiatku toto:
T.j. dôvod prečo to ide každých 5sek. je jasný.
S tým AT+CCLK? som len v začiatkoch skúmania. Pri tom ako som preveroval knižnice tak som narazil na súbor GPRS_Shield_Arduino.cpp a tam som našiel funkciu GPRS::getDateTime. Asi ju skúsim použiť.
ešte raz ďakujem za snahu a nasmerovanie.
Mali ste absolútnu pravdu. Váš program vypísal trvanie funkcie presne 5145ms.
Potom som pozeral do súboru sim900.h kde je hneď na začiatku toto:
Kód: Vybrat vše
#ifndef __SIM900_H__
#define __SIM900_H__
#include <SoftwareSerial.h>
#include <Arduino.h>
#define DEFAULT_TIMEOUT 5 //seconds
#define DEFAULT_INTERCHAR_TIMEOUT 1500 //miliseconds
enum DataType {
CMD = 0,
DATA = 1,
};
S tým AT+CCLK? som len v začiatkoch skúmania. Pri tom ako som preveroval knižnice tak som narazil na súbor GPRS_Shield_Arduino.cpp a tam som našiel funkciu GPRS::getDateTime.
Kód: Vybrat vše
bool GPRS::getDateTime(char *buffer)
{
//If it doesn't work may be for two reasons:
// 1. Your carrier doesn't give that information
// 2. You have to configurate the SIM900 IC.
// - First with SIM900_Serial_Debug example try this AT command: AT+CLTS?
// - If response is 0, then it is disabled.
// - Enable it by: AT+CLTS=1
// - Now you have to save this config to EEPROM memory of SIM900 IC by: AT&W
// - Now, you have to power down and power up again the SIM900
// - Try now again: AT+CCLK?
// - It should work
//AT+CCLK? --> 8 + CR = 9
//+CCLK: "14/11/13,21:14:41+04" --> CRLF + 29+ CRLF = 33
//
//OK --> CRLF + 2 + CRLF = 6
byte i = 0;
char gprsBuffer[50];
char *p,*s;
sim900_flush_serial();
sim900_send_cmd("AT+CCLK?\r");
sim900_clean_buffer(gprsBuffer,50);
sim900_read_buffer(gprsBuffer,50,DEFAULT_TIMEOUT);
if(NULL != ( s = strstr(gprsBuffer,"+CCLK:"))) {
s = strstr((char *)(s),"\"");
s = s + 1; //We are in the first phone number character
p = strstr((char *)(s),"\""); //p is last character """
if (NULL != s) {
i = 0;
while (s < p) {
buffer[i++] = *(s++);
}
buffer[i] = '\0';
}
return true;
}
return false;
}
Kdo je online
Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 2 hosti