Arduino Polska Forum

Pełna wersja: Sterowanie przekaźnikiem za pomocą SMS (Arduino UNO + moduł GSM)
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Witam, czy mogę prosić o podpowiedź jak zmodyfikować poniższy kod, żeby konkretny sms np o treści ALARM powodował załączenie się przekaźnika na danym pinie? Chodzi mi o to jak te pojedyncze znaki w zmiennej char c wykorzystać w ifie do porównania z jakimś konkretnym wyrazem - zapewne po wyrażeniu (c = sms.read()). Jakoś nie potrafię sam wymyśleć jak zrobić tablicę, która by ściągała dane z sms.read() i  potem program porównujący znaki w tej tablizy z konkretnym wyrazem np. ALARM)


Kod:
// include the GSM library
#include <GSM.h>

// PIN Number for the SIM
#define PINNUMBER ""

// initialize the library instances
GSM gsmAccess;
GSM_SMS sms;

// Array to hold the number a SMS is retreived from
char senderNumber[20];

void setup() {
 // initialize serial communications and wait for port to open:
 Serial.begin(9600);
 while (!Serial) {
   ; // wait for serial port to connect. Needed for native USB port only
 }

 Serial.println("SMS Messages Receiver");

 // connection state
 boolean notConnected = true;

 // Start GSM connection
 while (notConnected) {
   if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
     notConnected = false;
   } else {
     Serial.println("Not connected");
     delay(1000);
   }
 }

 Serial.println("GSM initialized");
 Serial.println("Waiting for messages");
}

void loop() {
 char c;

 // If there are any SMSs available()
 if (sms.available()) {
   Serial.println("Message received from:");

   // Get remote number
   sms.remoteNumber(senderNumber, 20);
   Serial.println(senderNumber);

   // An example of message disposal
   // Any messages starting with # should be discarded
   if (sms.peek() == '#') {
     Serial.println("Discarded SMS");
     sms.flush();
   }

   // Read message bytes and print them
   while (c = sms.read()) {
     Serial.print(c);
   }

   Serial.println("\nEND OF MESSAGE");

   // Delete message from modem memory
   sms.flush();
   Serial.println("MESSAGE DELETED");
 }

 delay(1000);

}
Na wiadomość zrób taki sam bufor jak na numer.
Wiadomość wczytaj do do tego bufora zamiast drukować na terminal.
Rozkaz umieść w znakach rzadko używanych, tak by można było łatwo go wyłowić.
Wiadomość podziel sobie funkcjami strtok() i porównuj funkcją strcmp(). Są też funkcje które sprawdzą czy w tekście jest po prostu słowo ALARM, ale może być innym kontekście.


Kod:
// include the GSM library
#include <GSM.h>

// PIN Number for the SIM
#define PINNUMBER ""

// initialize the library instances
GSM gsmAccess;
GSM_SMS sms;

// Array to hold the number a SMS is retreived from
char senderNumber[20];
char massage[128]; //można mniejszy bufor i po prostu uciąć wiadomość, jeśli zwykle tekst jest krótszy

boolean stringComplete = false;  // whether the string is complete

void setup() {
// initialize serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
  ; // wait for serial port to connect. Needed for native USB port only
}

Serial.println("SMS Messages Receiver");

// connection state
boolean notConnected = true;

// Start GSM connection
while (notConnected) {
  if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
    notConnected = false;
  } else {
    Serial.println("Not connected");
    delay(1000);
  }
}

Serial.println("GSM initialized");
Serial.println("Waiting for messages");
}

void loop() {
char c;

// If there are any SMSs available()
if (sms.available()) {
  Serial.println("Message received from:");

  // Get remote number
  sms.remoteNumber(senderNumber, 20);
  Serial.println(senderNumber);

  // An example of message disposal
  // Any messages starting with # should be discarded
  if (sms.peek() == '#') {
    Serial.println("Discarded SMS");
    sms.flush();
  }

  // Read message bytes and print them
  while (c = sms.read()) {
//Serial.print(c);
if(c == '\n')
     {
        // End of record detected. Time to parse

       
         [index] = 0;
         index = 0;
       stringComplete = true;
     }
     else
     {
       [index++] = c; //trzeba jeszcze dodać sprawdzenie czy bufora nie przekrecamy
       [index] = '\0'; // Keep the string NULL terminated
        
     }

Serial.println(massage);
//    
  }
if (stringComplete)
{
    char * smsik=massage;
    Serial.print("Otrzymane polecenie: "); //typu haslo&ALARM&
    Serial.println(smsik);
 
char* command1 = strtok(smsik, "&");

if (strcmp(command1 , "haslo")==0)
{  //jesli tresc SMS zaczyna się inaczej to trzeba
//to wyluskac dodajac np. &haslo&ALARM& i porownanie robic w kolejnym kroku
if (command1 != 0)
{
 
  Serial.println(command1); //drukowanie mozna wyrzuc, na czas testow by bylo
 command1 = strtok(NULL, "&"); // tu już powinno być slowo ALARM lub powtorzyc "luskanie"
//wazne ze tu juz podajemy NULL, tak samo w kolejnych krokach jesli wymagane
if (strcmp(command1,"ALARM")==0) wywolajdzialanieAlarmu(); //Twoja funkcja alarmu   wywolajdzialanieAlarmu()
}



}


  Serial.println("\nEND OF MESSAGE");

  // Delete message from modem memory
  sms.flush();
  Serial.println("MESSAGE DELETED");
}

delay(1000);

}
Nie mam jak przetestować, coś w ten deseń. Dodatkowe zadanie to usunąć to co dodaje wstawki html w code, nie wiem co robię źle jak piszę wewnątrz code.
(03-02-2018, 01:32)kaczakat napisał(a): [ -> ]Na wiadomość zrób taki sam bufor jak na numer.
Wiadomość wczytaj do do tego bufora zamiast drukować na terminal.
Rozkaz umieść w znakach rzadko używanych, tak by można było łatwo go wyłowić.
Wiadomość podziel sobie funkcjami strtok() i porównuj funkcją strcmp(). Są też funkcje które sprawdzą czy w tekście jest po prostu słowo ALARM, ale może być innym kontekście
BARDZO DZIĘKUJĘ ZA POMOC!!! SPRÓBUJĘ TO JAKOŚ OGARNĄĆ I PRZETESTOWAĆ  Smile
Witam, prawie mi się udało, problem jest taki, że działa tylko 2 razy po wgraniu programu do Arduino - to znaczy jednym sms mogą włączyć diodę a drugim wyłączyć. Ale wygaszenie diody i kolejne wysłanie smsa o treści "on" już nie powoduje załączenia się diody. Co robię nie tak?

Kod:
#include <GSM.h>

// PIN Number
#define PINNUMBER ""

// initialize the library instance
GSM gsmAccess; // include a 'true' parameter for debug enabled
GSM_SMS sms;

char remoteNumber[20];  // Holds the emitting number
char smsData[80]; //tablica do przechowania smsa
byte smsIndex = 0; //Then, you create an index into the array
char c;

void setup()
{
 // initialize serial communications
 Serial.begin(9600);

 Serial.println("SMS Messages Receiver");

 // connection state
 boolean notConnected = true;

 // Start GSM shield
 // If your SIM has PIN, pass it as a parameter of begin() in quotes
 while(notConnected)
 {
   if(gsmAccess.begin(PINNUMBER)==GSM_READY)
     notConnected = false;
   else
   {
     Serial.println("Not connected");
     delay(1000);
   }
 }

 Serial.println("GSM initialized");
 Serial.println("Waiting for messages");

pinMode(13,OUTPUT);
digitalWrite (13, LOW);
 
}

void loop()
{
 // If there are any SMSs available()  
 if (sms.available())
 {
   Serial.println("Message received from:");

   // Get remote number
   sms.remoteNumber(remoteNumber, 20);
   Serial.println(remoteNumber);

   // This is just an example of message disposal    
   // Messages starting with # should be discarded
   if(sms.peek()=='#')
   {
     Serial.println("Discarded SMS");
     sms.flush();
   }

   // Read message bytes and print them. Read and (effectively) throw away all but the last character from the message.
   while(c=sms.read())
   {
   smsData[smsIndex++] = c;}
        smsIndex = 0;
   //-Serial.println("\nEND OF MESSAGE");
   // delete message from modem memory
   sms.flush();
   Serial.println("MESSAGE DELETED");
if (strcmp(smsData, "on") == 0)
{Serial.println("OKAY");
digitalWrite (13, HIGH);
}
else
{Serial.println("NO");
digitalWrite (13, LOW);
}
 delay(1000);

 }}
Witam.
Pominąłeś sekcję podziału wiadomości i znaki sterujące. Wiadomość SMS nie musi kończyć się znakiem nowej linii, jest to jakiś znak CTR+Z  (0x1A być może biblioteka to już robi). Nie kończysz tablicy char znakiem 0 (może jest tam i tak w bilbiotece, a może nie).
Ale jest to istotne dla   strcmp(), dla niej jest ważna każdy znak i jego wielkość. Jeśli drugi komunikat (OFF) jest dłuższy niż pierwszy (ON), to pierwszy wysłany jako trzeci w buforze=[O,N,F,0] co nie jest =="ON". Poza tym drukuj sobie co jest w buforze aktualnie - to może być bardziej pomocne niż Twoje wrażenie co tam być powinno (gotowe komunikaty).  Nawet czasami drukowanie jako bajt może pomóc, by zobaczyć znaki niedrukowalne. No i zastąp if  strukturą switch...case (tylko komendy trzeba by zapisać jako typ wyliczeniowy) lub po prostu w każdym if sprawdzaj warunek. Teraz włącza na ON, a wyłącza na cokolwiek. Możesz dorobić sobie dwa klawisze i potestować czy można włączyć SMS, wyłączyć klawiszem i vice versa (komenda z terminala arduino tak samo). Jak znajdę taki moduł i chwilę czasu to przetestuje kod.
Edit:
Rozumiem, że załapałeś, że wysłanie "of" zamiast "off" (czy jakichkolwiek 2 znaków) załatwia sprawę i nie drążysz tematu. W każdym bądź razie przetestowałem i tak właśnie jest. Brakuje dopisywania 0 na końcu odebranej wiadomości do bufora. Jak by ktoś chciał się pobawić tym kodem, to Arduino komunikuje się softserialem uruchmianym biblioteką wbudowaną w GSM.h z pinu 2 do TX modemu, z pinu 3 do RX modemu. Miłej zabawy.
Dopiero niedawno dotarło do mnie kilka podstawowych kwestii:
- komunikacja ARDUINO - MODUŁ SIM może odbywać się bezpośrednio z komendami AT albo z wykorzystaniem biblioteki np. GSM.h 
- jeśli komunikacja przy użyciu komend AT, to albo w trybie tekstowym albo PDU. Tryb tekstowy jest łatwiejszy.

Dla laików takich jak ja polecam:
http://www.developershome.com/sms/smsIntro.asp
http://www.jarzebski.pl/arduino/komponen...im908.html

Zaktualizowany cel mam zatem taki, żeby napisać kod z komendami AT w trybie tekstowym (bez biblioteki GSM.h) , dzięki któremu będę mógł SMSem o konkretnej treści włączyć np. diodę na pinie 13.

Dotarłem do ciekawego kodu, w którym chyba jest to, co potrzebuję:
https://www.cooking-hacks.com/forum/view...=43&t=8183

Kod:
int8_t answer;
int x;
int onModulePin= 2;
char aux_string[30];
char SMS[200];
float fSMS;

char data[20];

void setup(){

   pinMode(onModulePin, OUTPUT);
   Serial.begin(115200);  

   Serial.println("Starting...");
   power_on();

}


void loop(){


Serial.println("Setting SMS mode...");
   sendATcommand("AT+CMGF=1", "OK", 1000);    // sets the SMS mode to text
   sendATcommand("AT+CPMS=\"SM\",\"SM\",\"SM\"", "OK", 1000);    // selects the memory

   answer = sendATcommand("AT+CMGR=1", "+CMGR:", 2000);    // reads the first SMS (since all other messages are deleted from previous delete statment)
   if (answer == 1)
   {
       answer = 0;
       while(Serial.available() == 0);
       // this loop reads the data of the SMS
       do{
           // if there are data in the UART input buffer, reads it and checks for the asnwer
           if(Serial.available() > 0){    
               SMS[x] = Serial.read();
               x++;
               // check if the desired answer (OK) is in the response of the module
               if (strstr(SMS, "OK") != NULL)    
               {
                   answer = 1;
               }
           }
       }while(answer == 0);    // Waits for the asnwer with time out
       
       SMS[x] = '\0';
       
 // parse the string
   strtok(SMS, ",");
   strtok(NULL, ",");
   strtok(NULL, ",");
   strtok(NULL, "\n");
   strcpy(data,strtok(NULL, ""));
 
   Serial.println(SMS);    
       
   fSMS= atof (data); // Convert the char array to floating point
   Serial.println(fSMS);
   
   }
   else
   {
       Serial.print("error ");
       Serial.println(answer, DEC);
   }
   
   Serial.println("AT+CMGDA= \"DEL ALL\""); //delete all messages from SIM card
   delay(10000);
   
}

void power_on(){

   uint8_t answer=0;
   
   // checks if the module is started
   answer = sendATcommand("AT", "OK", 2000);
   if (answer == 0)
   {
       // power on pulse
       digitalWrite(onModulePin,HIGH);
       delay(3000);
       digitalWrite(onModulePin,LOW);
   
       // waits for an answer from the module
       while(answer == 0){     // Send AT every two seconds and wait for the answer
           answer = sendATcommand("AT", "OK", 2000);    
       }
   }
   
}

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

   uint8_t x=0,  answer=0;
   char response[100];
   unsigned long previous;

   memset(response, '\0', 100);    // Initialice the string

   delay(100);

   while( Serial.available() > 0) Serial.read();    // Clean the input buffer

   Serial.println(ATcommand);    // Send the AT command


       x = 0;
   previous = millis();

   // this loop waits for the answer
   do{
       // if there are data in the UART input buffer, reads it and checks for the asnwer
       if(Serial.available() != 0){    
           response[x] = Serial.read();
           x++;
           // check if the desired answer is in the response of the module
           if (strstr(response, expected_answer) != NULL)    
           {
               answer = 1;
           }
       }
       // Waits for the asnwer with time out
   }while((answer == 0) && ((millis() - previous) < timeout));    

   return answer;
}


Niestety blokuje mnie kilka zasadniczych kwestii, których cały czas nie rozumiem:
1. Jak przekazać do Arduino polecenie, by zakończył przenoszenie wiadomości SMS do tablicy z ostatnim znakiem tej wiadomości - gdy nie jest znana jej długość
2. Jak wyłuskać z polecenia "AT+CMGR=1" samą treść wiadomości - czyli jak dokładnie działa parsowanie z wykorzystaniem strtok?
3.  Jak dokładnie działa funkcja strstr - czyli jak porównać tablicę znaków ze zdefiniowanym wcześniej łańcuchem?
4. Dlaczego do sprawdzenia zawartości bufora w pamięci raz są stosowane polecenia IF a innym razem WHILE - jak w powyższym kodzie: 
if(Serial.available() > 0){  
while(Serial.available() == 0);

Będę bardzo wdzięczny za pomoc!
Marek
Witam
Zmieniłeś całkowicie szkic, a tamten działał, wystarczyło do bufora dopisać zero na końcu tablicy  (ten z 03-02-2018, 12:37)
1. Nie kończysz, odbierasz wszystko. Różne sprzęty różnie reagują na przerwanie odbioru. Jeśli bufor ma np. [12] bajtów to po odebraniu dwunastego znaku przestajesz inkrementować zmienną index i wtedy wszystko wlatuje do ostatniej komórki ciągle ją zmieniając. Na koniec wpisujesz tam 0 i masz tablice char (string) =11 literek+0. To ważne by nie nadpisywać komórek pamięci za tablicą (w szczególności nie wpisujesz nic do tej tablicy dla index=12, bo tablica numerowana jest od 0 i jej ostatnia komórka jest pod indexem 11) , bo sobie robisz kuku. Czyli dla index =11 powinno być tam w komórce tablicy 0.
Analogicznie, gdy interesuje Cię tylko koniec wiadomości możesz wszystko do np. 34 znaku wrzucać do tablicy z index=0, a interesującą Cię wiadomość zapisać od index=0 do index=8 i zakończyć 0.
Możesz przerwać odbiór po prostu na podstawie wcześniej przyjętego  index>128, lub upłynął jakiś czas. Robisz break i zajmujesz się swoimi sprawami.
2. Masz bibliotekę, nie musisz tego robić. Biblioteka od razu daje treść wiadomości. Jeśli koniecznie chcesz to robić ręcznie to najpierw sprawdzasz jakie informacje dostajesz od modułu GSM, np.

Kod:
+CMGR: „REC UNREAD”, „numertelefonu”,””,”czas”
wiadomosc
No to tu widać, że Twoja wiadomość zaczyna się od nowej linii.  
Można więc tę część skrócić:
Kod:
// parse the string (TAK JEST)
  strtok(SMS, ",");
/*w tekście SMS szukaj przecinka i daj to co przed nim, reszta "w pomięci" , a z tekstu
<+CMGR: „REC UNREAD”, „numertelefonu”,””,”czas”\nwiadomosc> gdyby tu było przypisanie do zmiennej
to znalazłoby się w niej <"+CMGR: „REC UNREAD”">, sam przecinek jest zjadany, do obróbki zostaje
< „numertelefonu”,””,”czas”\nwiadomosc>

*/
  strtok(NULL, ",");
/*
to wywołanie z NULL oznacza kontynuacje czyli rozważana jest tylko dalsza część pierwotnego stringa
"w pamięci", znowu nie ma przypisania np. char* wyraz=strtok(NULL,","); więc tylko go obcina
za numeru telefonu
tu jest już tylko część <””,”czas”\nwiadomosc>
*/
  strtok(NULL, ","); //wycina ""
  strtok(NULL, "\n"); //wycina czas i zjada znak nowej linii \n
  strcpy(data,strtok(NULL, "")); //nic nie wycina?, nie wiedziałem że tak można, a jednocześnie
//robi   kopię do stringa data (czy tam faktycznie tablicy znaków char)
lub po skróceniu:
strcpy(data,strtok(SMS, "\n")); //wyrzuca wszystko przed i z newline \n, kopiuje do data

3. funkcji podajesz dwa argumenty, stringi, jak w pierwszym jest drugi to zwraca coś>0. strstr("sciananosna","ana") da 1, tak samo jak strstr("ana","ana"). Tym czymś jest wskaźnik do pierwszej dopasowanej litery lub gdy dopasowania brak to wskaźnik zerowy. Ważne że if się spełni zawszy gdy drugi zawiera się w pierwszym. Użyta wcześniej funkcja strcmp(string1,string2) zwraca 0 (dla odmiany) tylko w drugim przypadku, gdy każda litera jest zgodna.

4. Te funkcje nie sprawdzają zawartości bufora. if(Serial.available() > 0) sprawdza czy jest jakiś znak oczekujący do odebrania z magistrali UART. Może też być while(Serial.available() > 0) odczytujzUART;. Druga używana jest do dwóch rzeczy. 1 to sprawdzenie czy ciągle nic nie ma na uart? while(Serial.available() == 0); a dalsza część kodu zmusza program do wysyłania ciągle komendy AT. W tym modemie nie ustawiasz jaką ma mieć prędkość UART (domyślnie jest 115200). Wysyłasz mu ze swoją prędkością znaki, a modem po kolei sprawdza i dopasowuje, jak dopasuje to przyleci zrozumiałe OK, warunek nawiązania połączenia się spełni i program ruszy dalej, jak nie to będzie tu wisiał. Lub już po nawiązaniu połączenia i po wysłaniu jakiegoś polecenia AT, gdy nic nie zrobisz bez odpowiedzi, też program zostaje zapętlony i czeka na odpowiedź.

A o wszystkim można poczytać tu:
https://pl.wikibooks.org/wiki/C
Stokrotne dzięki Dobry Człowieku !!!
Chylę czoło za chęć pomocy i chętnie się odwdzięczę jeśli będę potrafiłSmile

Potrzebuję parę chwil, żeby mój skromny umysł przyswoił nowe mądrości. I jeśli przyswoi to dam znać Smile  ...a jeśli nie przyswoi to dam znać jeszcze prędzej  Big Grin Big Grin Big Grin 
W każdym razie szacun!
Mar
Witam znowu. Faktycznie ten pierwszy kod (z wykorzystaniem biblioteki GSM.h) było najłatwiej doprowadzić do używalności Smile  Załączam go tu, bo może komuś się przyda.

Kod:
//PROSTY PROGRAM DO WYZWALANIA AKCJI ZA POMOCĄ SMSA
// UWAGA - NIE UŻYWAĆ POLSKICH ZNAKÓW
//PROGRAM PONIŻEJ WYKORZYSTUJE STANDARDOWĄ BIBLIOTEKĘ ARDUINO STWORZONĄ DLA SHIELDA GSM
//PROGRAM SPRAWDZA  CZY NUMER TELEFONU, Z KTÓREGO WYSŁANO SMS JEST JEDNYM Z 2 DOZWOLONYCH
// UWAGA!!! - TRZEBA PODŁĄCZYĆ TX MODUŁU GSM DO PIN 2 ARDU UNO i RX MODUŁU GSM DO PIN 3 ARDU UNO

#include <GSM.h>
#define PINNUMBER "" // PIN Number

GSM gsmAccess; // initialize the library instance. Include a 'true' parameter for debug enabled
GSM_SMS sms;

char remoteNumber[20];  // Holds the emitting number
char smsData[80]; //tablica do przechowania smsa
byte smsIndex = 0; //Then, you create an index into the array
char c;

void setup()
{
pinMode(13,OUTPUT);
digitalWrite (13, LOW);

Serial.begin(9600);  // initialize serial communications
Serial.println("SMS Messages Receiver");
boolean notConnected = true; // connection state
 while(notConnected) // Start GSM shield.  If your SIM has PIN, pass it as a parameter of begin() in quotes
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);
}
}
Serial.println("GSM initialized");
Serial.println("Waiting for messages");
}

void usun_sms()
{
sms.flush(); // delete message from modem memory
Serial.println("MESSAGE DELETED");  
}

void wiadomosc()
{
/* This is just an example of message disposal    
Messages starting with # should be discarded
if(sms.peek()=='#')
{
Serial.println("Discarded SMS");
sms.flush();
}*/
while(c=sms.read()) // Read message bytes and print them. Read and (effectively) throw away all but the last character from the message.
{
smsData[smsIndex++] = c;
}
smsData[smsIndex] = '\0';  // Keep string NULL terminated. Ważne, aby ostatnia komórka w tablicy została nadpisana znakiem końca łańcucha
smsIndex = 0; //na koniec trzeba przywrócić początkowy numer indeksu
usun_sms();
if (strcmp(smsData, "on") == 0) //porównanie łańcucha znaków w tablicy ze zdefiniowanym łańcuchem
{
Serial.println("OKAY");
digitalWrite (13, HIGH);
}
else
{
Serial.println("NO");
digitalWrite (13, LOW);
}
delay(1000);
}

void loop()
{
// If there are any SMSs available()  
if (sms.available())
{
 Serial.println("Message received from:");
   sms.remoteNumber(remoteNumber, 20);   // Get remote number
  Serial.println(remoteNumber);
  if(strcmp(remoteNumber, "+48xxxxxxxxx") == 0 || strcmp(remoteNumber, "+48xxxxxxxxx") == 0)
 wiadomosc();
 else
 usun_sms();
}
}
 
Kaczakat, jeszcze raz bardzo Ci  dziękuję! Dzięki Tobie zacząłem rozumieć jak komunikować się komendami AT. (tym bardziej dziękuję, że jak widzę niestety niewiele osób w naszym wspaniałym kraju chce się bezinteresownie dzielić wiedzą z innymi...)
Na zakończenie chętnie zapytam jeszcze o parę kwestii:
1. Czy można wykorzystać tablicę znaków w konstrukcji switch case? na zasadzie: "jeśli w tablicy znajdzie się SMS1 to ... a jeśli SMS2 to... a jeśli SMS3, to...."
2. Czy są jeszcze jakieś inne przydatne polecenia do obróbki łańcuchów w tablicach typu str? - inne niż strstr, strtok, strcmp, strcpy?
3. Czym się różni "char dane[]" od "char* dane" ? Czytałem trochę o wskaźnikach, ale dalej nie rozumiem Sad
4. Co daje "F" w poleceniu Serial.println(F("ERROR"));?  
5. Czy dobrze rozumiem, że pętla While będzie realizowana tak długo, jak długo w buforze pamięci będą jakieś nieściągniętę bajty?
Pozdrawiam serdecznie!
Mar
Nie jestem programistą, więc mi chleba nie odbierasz ucząc się programować Big Grin. A tak na prawdę po prostu to nie jest popularne hobby, a to to nie jedyna strona w sieci.
Jak będziesz chciał zrobić coś więcej to musisz sobie zdobyć/poukładać wiedzę, przeczytać jakiś książki/poradniki od A do Z o c, c++, AVR, Arduino. Ja Ci odpowiem na te 5 pytań, ale nie wiesz, że powinieneś znać odpowiedzi na kolejnych kilkuset?
Do switch case można wykorzystywać liczby całkowite, więc nie może to być tablica, element tablicy już tak. Znak/char jest o tyle szczególny, że jest to liczba całkowita wielkości 1 bajta. Można sobie pokierować funkcją np. w 4 znaku SMS wysyłając znak sterujący i podać go SMS[3] do switch case, pod tym elementem będzie char '1', '2' lub '3'. Może też być użyty typ wyliczeniowy, który pod przyjaznymi nazwami kryje po prostu liczby.
Dałem Ci link wcześniej, a tam cały dział o napisach, pewnie nie wyczerpujący informacji - jest mnóstwo funkcji. Kopiowanie, obcinanie, konwersja na napisy liczb i odwrotnie. Arduino ma na stronie cały dział poświęcony String i kolejne funkcje specyficzne dla Arduino/C++.
Tablica jest zafiksowana, w sensie jej wielkość jest deklarowana jawnie [] lub ilością elementów, char *dane to namiastka stringa, ale faktycznie dalej tablica znaków o wielkości przypisanego napisu. Nie wiem jak działa mechanizm, wolę nie zmieniać zawartości *napis bo skoro jest to tablica a przypiszę większy napis to pojadę po losowych komórkach pamięci za tablicą. Robiłem testy i nic nigdy się takiego nie działo, może kompilator robi z tego jakąś dynamiczną tablicę?
F() to funkcja, makro, specyficzna dla Arduino, które nakazuje pozostawić napis we flash, zobacz jak zmienia się wolne miejsce RAM po kompilacji, gdy użyjesz F() do napisu i gdy go nie użyjesz. Normalnie każdy użyty napis jest po uruchomieniu wczytany do RAM i zajmuje tam miejsce. W Arduino/AVR są specjalne polecenia/funkcje deklarujące napisy i inne zmienne jako przeznaczone do przechowywania we flash i specjalne funkcje do odwoływania się do nich do flesh przed użyciem. Normalnie jest to upierdliwe, a makro F() to bardzo ułatwia. Jak się robi rozbudowany system komunikatów to można szybko zjeść dostępną pamięć i jest to jedyne wyjście - trzymać napisy we flash. Oczywiście jest też wolniejszy dostęp do takich danych.
While działa tak długo, jak warunek wewnątrz jest różny od 0, char to liczba, koniec stringa to 0. Tu akurat jest ważne co wpadło do zmiennej c, czy jest to jakiś znak czy 0.
Stron: 1 2