Arduino Uno host -- GSM 900 shield stabil együttműködése?

Az oldal Demopaneljeinek _hardware_ kérdései...
Válasz küldése
vitalyos
Újonc
Újonc
Hozzászólások: 3
Csatlakozott: 2018. május 14. hétfő, 11:11

Arduino Uno host -- GSM 900 shield stabil együttműködése?

Hozzászólás Szerző: vitalyos »

Barátaim,

a feladatom az, hogy egy víkendház fűtését távolról, SMS-sel ki- és bekapcsoljam. Persze, válasz SMS-t is szeretnék kapni, hogy igen gazdi, bekapcsoltam, a hőmérséklet ennyi és ennyi.

A feni konfigurációt szerezem be itt a TÁVIR-tól. Az SMS küldéssel és fogadással nincs is baj, saját C++ programból rendesen működik.

A GSM felé SoftwareSerial-t használok, a neten olvasható példaprogramok szerint. Pin 7. és 8.
A kijelző konzol LiquidCrystal_I2C.
A táp 12V 2A-t tud, és az Arduino-ba van dugva. (A GSM-be nem dughatom, nem megy le az Arduino-hoz.)

De ez a konfiguráció nem működik stabilan. A LiquidCrystal_I2C nélkül sem. Néhány perc vagy óra után kiakad, leghosszabban fél napig működött. A kiakadásnak több fajtája van:

- a host és a GMS kapcsolata megszakad úgy, hogy a GSM nem küld adatot a host-nak. Sem arról, ha SMS jött, sem választ, ha a host időt, vagy akármi mást kérdez tőle. Ilyenkor az available()==0 értéket ad.

- A C++ program belefagy az available()vagy a read() függvényekbe.

- A tápfesz kezd elmenni, a led-ek és a konzol hunyorognak, és a szerkezet - anélkül, hogy a host POWER DOWN üzenetet kapna -, elkezd újra boot-olni, és elindulás után ciklusban boot-ol.

A kiakadás nem az SMS-kezeléssel kapcsolatos, akkor is kiakad, ha nem kap SMS-t.

------------
Barátaim, ezt az egyszerű alapfeladatot, egy primitív SMS-gép építését már biztosan sokan megoldottátok. Tehát elsősorban nem ötleteket kérek, hogy mit próbáljak meg. Olyanok jelentkezzenek, akiknek ez - vagy hasonló - konfiguráció stabilan működik.

Egy ilyen egyszerű gépnek korlátlan ideig autonóm módon kell működnie. Az nem baj, ha pl. magától újra boot-ol, de minden helyzetben a talpára kell essen. Az sem baj, ha URC-t (Unsolicited Result Code-t) küld a hostnak, pl főnök, baj van ingadozik a táp, vagy túlmelegedtem, vagy valami, akkor már a fejlesztés stádiumában rá lehet jönni, hogy mi a baj.

Tehát: működik valakinek ez - vagy hasonló - konfiguráció autonóm módon stabilan? Egy hét stabil működés már meggyőző lenne.

Üdvözlet
Vitályos Gábor
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Arduino Uno host -- GSM 900 shield stabil együttműködése?

Hozzászólás Szerző: Robert »

Javaslom a TavIR-féle tápot használni hozzá (9V-os, amit az egyeztetés során megkapott), mert akkor elhangzott: a saját 12V-os táppal nem volt stabil a rendszer.

Javaslat: vissza a tesztelt és működő táphoz, vagy a 12V-os tápot cserélni kell.
A 12V táp problémája:
Az Arduino 5V-os stabilizátor IC-je állítja elő a a LCD áramokat (háttér ~70mA, arduino és sallangok ~70 mA).
Így a 5V stabIC ~1.5W elfűtését végzi a kis hűtőfelületen. Túlmelegszik - ez a hunyorgás oka is. (12V-5V)*0.15A
A táp 12V 2A-t tud, és az Arduino-ba van dugva. (A GSM-be nem dughatom, nem megy le az Arduino-hoz.)
Átkötés a GSM tápbemenet és a UNO lapka Vin pontja közt?

Az UNO lapon a betáp ágban 1-2A-es dióda van. A GSM modul standard SIM900-as, amin kapcsolóüzemű táp van (4.2V@2A max áramfelvétel -> 12V@0.7A jelent)

A program kódot is jó lenne látni.
- memóriafoglalás/kezelés rendben? SMS hossza max 12x160 karakter lehet (160 karakterrel mindenképp számolni kell).
- szoftvar serial sebessége max 9600 bps lehet.
- GSM élesztése AT-OK párossal kell történjen (kisbetű-nagybetű érzékeny). Javasolt a GSMben nem autobaud-ot használni, hanem fix 9600bps-re konfigurálni.
http://www.tavir.hu - a gazda :)
vitalyos
Újonc
Újonc
Hozzászólások: 3
Csatlakozott: 2018. május 14. hétfő, 11:11

Re: Arduino Uno host -- GSM 900 shield stabil együttműködése?

Hozzászólás Szerző: vitalyos »

Kipróbáltam a javasolt TavIR-féle 9V (1A) tápegységet, de ezzel sem jó.

Bár stabilabban működik, de néhány óra, fél nap működés után így is kiakad. A kiakadás módja ugyanaz, mit amit a nyitó posztban leírtam. A kiakadás pillanatát néha el lehetett csípni, olyankor egy induktív háztartási gép -- PC, hűtő -- ki-be kapcsolásával egyszerre történt.

Akkor tehát kipróbáltam 5V 2A, 9V 1A és 12V 2A feliratú adapterekkel is, lényegében azonos eredménnyel.

Mindebből arra következtetek, hogy az Arduino Uno -- GSM shield tandem feszültségstabilizálása nem megfelelő.

Ha a kiakadás olyan, hogy a GSM lehal és a host életben marad, akkor a tápfesz kapcsolásával a host talán életre rugdalhatja a GSM-et, erről sem olvasok semmit, ezt is ki kellene kísérletezni. Azonban a fordított eset is előfordul: a GSM ledjei vidáman pislognak tovább, a térerőt érzékeli, a host pedig beleragad egy available()-ba.

----------
A programkódot mellékelem. Ki van hagyva belőle minden adatkezelési funkció. Az adatokat beolvassa, kiírja a Serial-ra és az LCD-re, és eldobja. AT transparensként is működik.

2000ms-onként lekérdezi az időt AT+CCLK? paranccsal, közben 1000ms-onként olvas úgy, hogy 100ms time-out-tal összevár egy blokkot, ami általában egy válasz a transparen AT-ra, vagy egy idő. A blokkot kiírja a Serial-ra szövegesen (, és ha nem idő, kiírja a betűk decimális kódját is). Ha idő jött, kiírja az LCD-re. Továbbá életjelként 1000ms-onként kiírja az eltelt időt is az LCD-re. Tele van szurkálva trace-ekkel: lcd_UpRightTrace, ami most ki van kötve. Ha visszakötjük, lehet nézni, hogy hol pusztult el, és az utolsó 6 trace-nek a történetét. Ezekből további következtetéseket nem tudtam levonni.

(Szükség van az LCD-s marhaságokra, másképpen nem lehet utólag megállapítani, hogy mi történt. A PC másra is kell, és az IDE Serial kommunikációja nem mindig áll helyre az újraindulás után.)

Serial-ról olvasás: int serialread(char *result, int timeout)
GSM-ről olvasás: int sim900blockread(char *result, int timeout)

A SoftwareSerial.h-ban:
#define _SS_MAX_RX_BUFF 256 // RX buffer size

------------
programkód helye: https://www.dropbox.com/s/tupr1ix2j0jvh ... e.ino?dl=0

-------------------------- a programkód, ha a DropBox elérhetetlen:

Kód: Egész kijelölése

#include <Wire.h>
#include <EEPROM.h>  

#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>   // LCD kijelző include file

SoftwareSerial SIM900(7, 8); 
LiquidCrystal_I2C lcd(0x3f,20,4);  //LCD 

/* ------------------------ Status kijelzése az lcd-n és SMS-en

                       heat_start          heat_duration      wind_start          wind_duration

Nincs                  -                   -                  -                   -
Későbbi start esetén   hó/nap/óra/perc     óra/perc           ++óra/perc          óra/perc
Heat folyamatban       *                  +óra/perc           ++óra/perc          óra/perc
Hind folyamatban      (hó/nap/óra/perc     óra/perc)          *                   +óra/perc
Lejárt                (hó/nap/óra/perc     óra/perc)         (++óra/perc          óra/perc)
--------------------------- */

struct STATE_EEPROM{
  int SMSnumber; 
//  date_time heat_start, heat_duration;    // absolute time
//  date_time wind_start, wind_duration;    // absolute time
} ee = {0};

char txt[257], ch;        // buffer for 1)GSM read, 2)Serial read, 3)GSM right
int txtlength = 0;        // length of txt[]

/* --------------------- SETUP --------------------- */
void setup() {
// put your setup code here, to run once:
// Configure software serial port

  Serial.begin(19200);
  while (!Serial); // wait for Serial 
  
  pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT);    // relay block

  pinMode(7, INPUT); pinMode(8, OUTPUT); //SIM900
  pinMode(9, OUTPUT);         // soft power to SIM900

//  pinMode(6,OUTPUT);          // --- ha OUTPUT, nem megy a GSM ?!
 
  pinMode(10,OUTPUT); pinMode(11,OUTPUT); pinMode(12,OUTPUT); pinMode(13,OUTPUT); // led
  
 
//  pinMode(A0, INPUT); // A1, A2, A3 
//pin A4 A5 --- // I2C

  lcd.init();
  lcd.setCursor(0,0); lcd.print(F("Stove ---"));
  Serial.println(F("Stove ---"));
  lcd.backlight();  // LCD inicializálás
  
  trace(0,0,"Stove, SIM900 ...");
  Serial.print("_ -jel azt jelenti: 13 es 10 karakter (CR, LF) jott egymas utan.");
  Serial.print("_="); Serial.println((int)('_'));
  SIM900.begin(9600);

//  SIM900.listen();
// Give time to your GSM shield log on to network
  delay(5000);

// ---- eeprom init load
//  trace(0,2,"Initial load...");
//  EEPROM.get(0, ee);
  trace(0,0,"Stove, SIM ok");

// --- set SIM900 to SMS text mode
  
  SIM900.print("AT+CMGF=1\r");
  delay(100);
  sim900blockread(txt, 100);

  SIM900.print("at+ipr=?\r");
  delay(100);
  sim900blockread(txt, 100);
  
  SIM900.print("at+ipr=?\r");
  delay(100);
  sim900blockread(txt, 100);
  
  SIM900.print("at+ciurc?\r");
  delay(100);
  sim900blockread(txt, 100);

// ---get clock from modem
  SIM900.print("AT+CCLK?\r");
  delay(100);
  sim900blockread(txt, 100);

  SIM900.print("AT+CCLK?\r");
  delay(100);
  sim900blockread(txt, 100);
  
  SIM900.print("AT+CCLK?\r");
  delay(100);
  sim900blockread(txt, 100);

  trace(0,0,"Stove, setup ok.");

} // SETUP

struct TIME {
  int y,mo,d,h,mi,s;
} time;

/* -------------------- LOOP ------------------- */
void loop(){
  

//sendsms("+36209320179","SMS from VG's Arduino ");
//sendsms("+36205560911","SMS from VG's Arduino ");

//sendsms("+36309506206","Letelt a fél év, üdvözöl az Arduino (VG) ");

while(1){

  char *str;  // for str_search in text read from GSM

{
// >>>>>>>>>>  life marker: elapsed time to LCD
unsigned long act_millis = millis();
  
   lcd.setCursor(6,1); 
   lcdprint2( act_millis/3600000/24 , '/');
   lcdprint2( (act_millis/3600000)%24 , ':');
   lcdprint2( (act_millis/60000)%60 , ':');
   lcdprint2( (act_millis/1000)%60 , ' ');

//<<<<<<<<<<< end of life marker: elapsed time to LCD
};
   lcd.setCursor(0,0); lcd.print("Stove ----          ");
   lcd_UpRightTrace('?');

  if(SIM900.isListening()){
    lcd_UpRightTrace('*');
  }else{
    lcd_UpRightTrace('X');
  };

  if(serialread(txt, 100)>=0){    // for transparent AT commands
 
    Serial.print(">>>>>>>>>---- ");
    Serial.print('{');Serial.print(txt);Serial.print('}');

    delay(200);
    SIM900.print(txt);
    SIM900.print("\r");

    Serial.println("bement");
  }else{;

    if(elapsed_millisec(2000)) SIM900.print("AT+CCLK?\r");
  };
 
  lcd_UpRightTrace('S');
  txtlength = sim900blockread(txt, 100);
  
  if(txtlength<0){      // Time Out, no received text. Do nothing
    lcd_UpRightTrace('-');

  }else{              // received something

    Serial.print("-- <<<<<<<<< [");
    Serial.print(txt);    // Kiírja a konzolra, ami jött
    Serial.println("]");

     if(str=str_search(txt,"+CCLK: ")){    // ===== time is read
      lcd_time(str);   // time to LCD
      txt[0]=0;

     }else{      // ===== no time response, must be some other thing
int errorn, x=0;
// trace on the lcd line 1.
//    txt[20]=0;
//    lcd.setCursor(0,1); lcd_fill(20, ' '); 
//    lcd.setCursor(0,1); /* lcd.print(errorn++); lcd.print('#'); */ lcd.print(txt);

//                 >>>> trace to the Serial

Serial.println();
while(txt[x]){
  Serial.print((int)(txt[x++]));  Serial.print(' ');
};
Serial.println();
//                 <<<< end of trace to the Serial
  

/* // power on:
      if(str=str_search(txt,"POWER DOWN")){ // ===== What? Power down?
       digitalWrite(9, LOW); delay(1000);
       digitalWrite(9, HIGH); delay(2000);
       digitalWrite(9, LOW); delay(3000);

      };
*/ // power on
    };       // time or other string 
  };  // time out or read something

 delay(1000);
}; // while(1)

} // LOOP()

/* =============================== LCD ============================ */

/* ----------------- */
void lcd_fill(int n, char ch)
{
int x=n;
while(x--) lcd.print(ch);
}

// -----------------
void lcd_table(int ll, int spaces)
{
  if(ll<spaces) lcd_fill(spaces-ll, ' ');
}

/* ----------------- */
void lcdprint2(int i, char txt)
{
  if(i<10) lcd.print('0');
  lcd.print(i);
  lcd.print(txt);
};

void trace (int x, int y, char *txt)
{
  Serial.println(txt);
  lcd.setCursor(x,y); lcd.print(txt);
}

/* ------------------ */
void lcd_time(char *str)
{  
// saves time text to STRUCT time and report to LCD

    time.y = text_to_int(str+8);
//Serial.print(time.y); Serial.println('/'); 
    time.mo= text_to_int(str+11);
//Serial.print(time.mo); Serial.println('/'); 
    time.d = text_to_int(str+14);
    time.h = text_to_int(str+17);
    time.mi = text_to_int(str+20);
    time.s= text_to_int(str+23);

    lcd.setCursor(0,3); 
    lcdprint2(time.y,'/'); lcdprint2(time.mo, '/');
    lcdprint2(time.d,'/');
    lcdprint2(time.h,':'); lcdprint2(time.mi,':');  lcdprint2(time.s, ' ');
};

/* =============================== text ============================ */

/* ----------------- */
char *int_to_text(int i)
{
static char result[10];
int ii=i, x=8;
result[9]=0;

  do{
    result[x--] = ii%10 + '0';
    ii /= 10;
  } while(ii);

return(result+x+1);
}

/* ----------------- */
int text_to_int(char *txt)
{int result=0;
char *txtn=txt;

while(*txtn<='9' && *txtn>='0') result = result*10 + *txtn++ - '0';
return(result);
}

/* =============================== modem ============================ */

// ---------------- sendsms
/* No sendsms in this test.  Transparent AT command does exist!
void sendsms(char *phonenumber, char *message)
{
  // AT command to set SIM900 to SMS mode
  SIM900.print("AT+CMGF=1\r"); 
  delay(100);

  // REPLACE THE X's WITH THE RECIPIENT'S MOBILE NUMBER
  // USE INTERNATIONAL FORMAT CODE FOR MOBILE NUMBERS
  SIM900.print("AT + CMGS = \"");
  SIM900.print(phonenumber);
  SIM900.println("\"");
  delay(100);
  
  // REPLACE WITH YOUR OWN SMS MESSAGE CONTENT
  SIM900.print(message);
  SIM900.print(" #");
  SIM900.println(++ee.SMSnumber);
  delay(100);

Serial.println("1. println volt");
  // End AT command with a ^Z, ASCII code 26clk=?
  SIM900.println((char)26); 
//  delay(100);
//  SIM900.println();
  // Give module time to send SMS
Serial.println("ures sor is volt");
  delay(5000); 
  
// ---- eeprom save after sending SMS
   Serial.print (F("Eeprom save..."));
   EEPROM.put(0, ee);
}
End of comment: No sendsms in this test.  Transparent AT command does exist!*/

/* -------------------- */
int sim900blockread(char *result, int timeout)
{
// result: read text, closed with 0
// timeout: wait (ms) in case of available==0
// Return: length of the result

  boolean was_timeout = false;
  unsigned long millisec = millis();
  int resultx;

   do{
    if(millis()-millisec>timeout) was_timeout = true;
   }while(!was_timeout && SIM900.available()==0);
   
lcd_UpRightTrace('s');
 
 
   if(!was_timeout){
     boolean was_read_after_delay = false;
     resultx = 0;
    
     do{
       char ch;

lcd_UpRightTrace('h');
SIM900.available();
lcd_UpRightTrace('i');
SIM900.available();
lcd_UpRightTrace('j');

        if(SIM900.available()==0 && was_read_after_delay){   //have to wait a little 
          delay(100);
          was_read_after_delay = false;
          result[resultx++]='|';
        };
lcd_UpRightTrace('d');

        if(SIM900.available()>0){  // can more read

//   Serial.println(SIM900.available());
  
lcd_UpRightTrace('f');

          ch = SIM900.read();

           if(ch==10 && result[resultx-1]==13){        
            resultx--;
            ch='_';
           };

          result[resultx++]=ch;
          was_read_after_delay = true;    // can more read
 
        }; // if. else: no more reqadable, end of the read. 

lcd_UpRightTrace('g');

     }while(was_read_after_delay); 
          
    result[resultx++] = 0; 

{static int maxresultx=0;
  if (resultx>maxresultx) maxresultx = resultx;
  lcd.setCursor(11,0);
  lcd.print(resultx); lcd.print('/'); lcd.print(maxresultx);lcd.print('.'); 
};  
return(resultx);
   }else{  // timeout 
//     Serial.println("Timeout, read new command:");
return(-1);
   };  //if not timeout, else timeout

}; //read block

/* ---------------------- */
int serialread(char *result, int timeout)
/*   result -1: timeout
     0..n: length of block    */
{
  boolean was_timeout = false;
  unsigned long millisec = millis();
  int resultx;

   do{
    if(millis()-millisec>timeout) was_timeout = true;
   }while(!was_timeout && Serial.available()==0);
   
   if(!was_timeout){
     resultx = 0;
     do{
        char ch;
        while ((ch=Serial.read()) < 0);
        result[resultx]=ch;
 //       Serial.print(result[resultx]); Serial.print(" = "); Serial.println( (int)(result[resultx]) );
     }while(result[resultx++] != 13);

     result[resultx++] = 0; 
 // Serial.println("Nem timeout ");
   }else{  // timeout 
 //    Serial.println("Timeout, read new SMS:");
return(-1);
   };  //if timeout

return(resultx);
} // serialread 

/* ---------------------- */
boolean elapsed_millisec(int delayed)
{static unsigned long millis0;
 boolean elapsed = (millis()-millis0) > delayed;
  if(elapsed) millis0 = millis();
return(elapsed);
};

/* ----------------------- */
char *str_search(char *txt, char *searched){
  char *result=NULL;
  
  char *txt0=txt;  //shifted by 1
  int txtx=0, searchedx=0;
  
  while(1){          // txt0, txtx, searchedx ==> next char, to compare
   if(txt0[txtx]=='|'){      // may be more '|'
     txtx++;
     continue;      // may be more '|'
   };
   if(!searched[searchedx]){ // ok, end of searched, break
     result=txt0;
     break;
   };
   if(!txt0[txtx]){
     break; // error, end of txt break
   };
   if(txt0[txtx]==searched[searchedx]){
     txtx++; searchedx++;   // continue
     continue;
   }else{
     txtx=0; txt0++; searchedx=0;
     continue;
   };
  }; // while(1)

return(result);
}; // char *str_search()



void lcd_UpRightTrace(char ch)
{int x;
static char trace_str[7] ="      ";
 return;
  trace_str[7]=0;
  for(x=0; x<7; x++)trace_str[x] = trace_str[x+1];
  trace_str[6]=ch;
  lcd.setCursor(13,0);
  lcd.print(trace_str);
 // delay(100);
}
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Arduino Uno host -- GSM 900 shield stabil együttműködése?

Hozzászólás Szerző: Robert »

Tippek:
1, Arduino lap kiakad:
Watchdog használata, ez újraindítja "kiakadáskor"
A kiakadás okának megkeresése: serial.avaiable() ? Ez érdekes - ez szoftver eltévedésre utal (buffer tulcsordulás), egyebek.

2, GSM restart
A PowerKey "megnyomás-szimulása" a modult ki majd bekapcsolja.

Egy "minimálprogrammal" tesztelném:
- lekérdezem az AT-val hogy él-e
- visszamegy a PC fele és időpecséttel (hiperterminal - igy látom mikor mi történt)

A modem initjeinél _nem_ kerül a válasz megvizsgálásra! Csak beolvassa a program a kapott adatot.
http://www.tavir.hu - a gazda :)
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: Arduino Uno host -- GSM 900 shield stabil együttműködése?

Hozzászólás Szerző: Robert »

A szoftveres sorosport is bekavarhat. Maga a programban sokminden történik (adatfeldolgozás, LCD kezelés, sorosporti kiírás/olvasás.
A szoftveres sorosport használhtósága NEM mérhető össze a valódi HW alapú sorosporttal...
Én azért egy Leonardoval is kipróbálnám: UNO csereszabatos, de a USB sorosport mellett _valódi_serial_ portja a D0/D1.
http://www.tavir.hu - a gazda :)
Válasz küldése