Wysyłanie wyniku AT+CSQ do ThinkSpeak

Masz problem z Arduino? Tutaj możesz szukać pomocy.
ODPOWIEDZ
pietra85
Młodszy majsterkowicz
Posty: 2
Rejestracja: 28 sty 2020, 21:12

Wysyłanie wyniku AT+CSQ do ThinkSpeak

Post autor: pietra85 » 28 sty 2020, 21:21

Witam,

Od 1,5 miesiąca uczę się programować Arduino Uno rev3 korzystając z zakupionego zestawu Forbot Arduino na Botlandzie. Przerobiłem tutoriale oraz spędziłem sporo godzin tworząc przykładowe projekty, jednakże nie potrafię ogarnąć jednej kwestii związanej z GSM AT Commands.

Aktualnie staram się stworzyć urządzenie sprawdzające zasięg GSM i wysłać tę informację na ThinkSpeak (albo inny serwis/php/excel sheets itp). Wysyłanie danych do ThinkSpeak, MySql, Google Sheets etc udało mi się osiągnąć, jednakże mam problem z wysłaniem mojej zmiennej, czyli zasięgu (który wywołuję komendą AT+CSQ i otrzymuję wartość w postaci +CSQ:18,99 , z której tylko cyfra 18 mnie interesuje).

Kod programu przesyłam poniżej.

Arduino Uno rev 3 wyposazyłem w DFRobot Shield GPRS SIM800C

Aktualnie arduino wysyła z "ręki" wpisaną stałą wartość 18, jednakże tutaj chciałbym aby pobierał dane z +CSQ i otrzymaną wartość dodał w wysyłany link.

z góry dziękuję za pomoc!

Kod: Zaznacz cały

//testing GSM signal strength and sending it to ThingSpeak

#include <SoftwareSerial.h> // I am using DFRobot Shield GPRS SIM800C therefore need to redirect RX and TX
#define SIM_800_RX 2
#define SIM_800_TX 3

SoftwareSerial MySerial(SIM_800_RX, SIM_800_TX);

int delayShort=1000; //time delays = 1 second
int delayMedium=3000; //time delays = 3 seconds
int delayLong=60000; //time delays = 60 seconds


void setup() {

  Serial.begin(9600);   // Open serial communications and wait for port to open:
  while (!Serial);
  MySerial.begin(9600);   // set the data rate for the SoftwareSerial port
  delay(delayShort);

  MySerial.println("AT");  // checking communication with GSM
  printGSMreply();  //expecting answer is OK
  delay(delayMedium);
  
  MySerial.println("at+csq");
  delay(delayShort);
  printGSMreply();  //expecting answer is +CSQ:18,99
  
  MySerial.println("at+cipshut");  //Close the GPRS PDP context - if deleted I am getting error message
  delay(delayShort);
  printGSMreply();  //expecting answer is OK
  
}

void loop() 
{ 
    sendToGsm(); //Start the GSM-Modul and start the transmisson
    delay(delayMedium); //Wait one minute
}

void sendToGsm() 
{

  MySerial.println("at+csq");
  printGSMreply(); //expecting answer is arround +CSQ:18,99 and would like to send number 18 to ThingSpeak
  delay(delayShort);

  MySerial.println("at+cstt=\"internet\",\"\",\"\"");
  printGSMreply();
  MySerial.println("at+ciicr");  //brings up the GPRS connection
  printGSMreply();
  MySerial.println("at+cifsr");//enquire my IP address allocated
  printGSMreply();
  MySerial.println("at+cipstart=\"TCP\",\"184.106.153.149\",\"80\"");//connect to the ThingSpeak IP address which will be translated as update URL (https:// api . thingspeak . com)
  printGSMreply();
  MySerial.println("at+cipsend=72");//declare the number of characters I want to send to ThinkSpeak plus +3 => in my case 69+3=72
  printGSMreply();
  MySerial.print("GET /update?");//this is a constant beginning for the GET command and is as provided by ThingSpeak
  printGSMreply();
  MySerial.print("api_key=ABCDEFGHIJKLMNOP");//the channel API key provided by ThingSpeak
  printGSMreply();
  MySerial.print("&field1=");
  printGSMreply();
  MySerial.println("18");//!!HERE I WOULD LIKE TO GET MY AT+CSQ VALUE!!
  printGSMreply();
  MySerial.println("at+cipack");//ask for acknowledge details
  printGSMreply();
  MySerial.println("at+CIPCLOSE");//close the IP connection  (mozna uzyc CIPSHUT
  printGSMreply();

  
}

void printGSMreply() //Print GSM Status
{ 
  while (MySerial.available()) {
    Serial.write(MySerial.read());
  }
}

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


stiven
Złota rączka
Posty: 1630
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Wysyłanie wyniku AT+CSQ do ThinkSpeak

Post autor: stiven » 29 sty 2020, 00:04

Zadeklaruj sobie przed setup() (jako zmienne globalne) zmienną typu char, tablicę typu char, oraz dwie zmienne typu int.

Kod: Zaznacz cały

char odp[20];
char znak;
int i;
int gsm;
Funkcję printGSMreply() zapisz tak

Kod: Zaznacz cały

void printGSMreply() //Print GSM Status
{ 
  i = 0;
  while (MySerial.available()) 
  {
    znak = MySerial.read();
    odp[i] = znak;
    Serial.write(znak);
    i++;
  }
}
Funkcja ta będzie działać tak jak do tej pory (otrzymany znak z jednego seriala wyświetlać na drugim serialu) i dodatkowo cały odebrany tekst będzie zapisany też w tablicy znaków odp[]. W odp[0] będzie pierwszy odebrany znak, w odp[1] drugi, itd. Po linijkach

Kod: Zaznacz cały

  MySerial.println("at+csq");
  printGSMreply(); //expecting answer is arround +CSQ:18,99 and would like to send number 18 to ThingSpeak
  delay(delayShort);
dodaj taką:

Kod: Zaznacz cały

  gsm = (odp[5] - 48) * 10 + (odp[6] - 48);
Przyjmując, że pierwsze 5 znaków odpowiedzi, to zawsze "+CSQ:", to będą interesowały nas 2 znaki kolejne, czyli 6 i 7, ale że pola w tablicach są liczone od 0, to 5 i 6. I tutaj dodatkowo trzeba zrobić tą "sztuczkę" z odejmowaniem "-48" a wynika to z tego, że operujemy na typie znakowym char i taki typ da nam w tym miejscu wartość jaka jest przypisana do danego znaku w tablicy ASCII. W tablicy ASCII 0 jest w polu 48, kolejne cyfry są w kolejnych polach, czyli jakby trzeba zmniejszyć o 48 daną wartość znaku, żeby otrzymać odpowiednią cyfrę.
No a później tam gdzie wysyłałeś wartość "18", wysłać zmienną gsm.

Kod: Zaznacz cały

  MySerial.print("&field1=");
  printGSMreply();
  MySerial.println(gsm);//!!HERE I WOULD LIKE TO GET MY AT+CSQ VALUE!!
uzi18
Majsterkowicz
Posty: 107
Rejestracja: 10 maja 2018, 05:06

Re: Wysyłanie wyniku AT+CSQ do ThinkSpeak

Post autor: uzi18 » 29 sty 2020, 13:21

uzyj jakiejs biblioteki np.: https://github.com/VittorioEsposito/Sim ... ry-revised
w tej masz gotowy odczyt przez metode: Sim800L::signalQuality()
wystarczy sprawdzic czy odp. jest poprawna i wyciagnac z niej liczbe ktora cie interesuje przez proste uzycie np. metody substring
stiven
Złota rączka
Posty: 1630
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Wysyłanie wyniku AT+CSQ do ThinkSpeak

Post autor: stiven » 29 sty 2020, 14:34

Rzeczywiście można też skorzystać z biblioteki i substring(). Ale ogólnie korzystanie z komend AT jest na tyle proste, że ja jeszcze dodam wariant bez biblioteki a z wykorzystaniem substring(). Teraz wystarczy zadeklarować globalnie (albo w loop()) tylko jedną nową zmienną

Kod: Zaznacz cały

  String gsm;
a pozostałe zmiany w kodzie wyglądałyby tak:

Kod: Zaznacz cały

String printGSMreply() //Print GSM Status
{ 
  String odp;
  char znak;
  
  while (MySerial.available()) 
  {
    znak = MySerial.read();
    Serial.write(znak);
    odp = odp + znak;
  }
  return odp;
}

Kod: Zaznacz cały

  MySerial.println("at+csq");
  gsm = printGSMreply(); //expecting answer is arround +CSQ:18,99 and would like to send number 18 to ThingSpeak
  delay(delayShort);

Kod: Zaznacz cały

  MySerial.print("&field1=");
  printGSMreply();
  MySerial.println(gsm.substring(5,7);//!!HERE I WOULD LIKE TO GET MY AT+CSQ VALUE!!
Funkcja printGSMreply() poza tym, że będzie wyświetlać tak jak wcześniej odpowiedź z jednego seriala na drugi, to dodatkowo będzie zwracać Stringa z tekstem odpowiedzi, w loop() będzie można sobie tą odpowiedź zapisać do stringa i operować na nim.

Linijka

Kod: Zaznacz cały

  gsm = printGSMreply(); //expecting answer is arround +CSQ:18,99 and would like to send number 18 to ThingSpeak
spowoduje i wyświetlenie odpowiedzi na serialu i jednocześnie zapisanie jej do zmiennej gsm.
pietra85
Młodszy majsterkowicz
Posty: 2
Rejestracja: 28 sty 2020, 21:12

Re: Wysyłanie wyniku AT+CSQ do ThinkSpeak

Post autor: pietra85 » 29 sty 2020, 22:04

dzięki Stiven za obszerną odpowiedź! opcja 1 i 2 zadziałały z czego #2 będzie dla mnie idealny. Dodatkowo nauczyłem się jak zapisywać inne wartości z AT command - dziękuję Ci bardzo!
Jedna uwaga, przy substring(5,7), wartość powinna być substring(15,19) gdyż serwer zwraca wartość:

Kod: Zaznacz cały

20:46:32.839 -> at+csq
20:46:32.839 -> +CSQ: 24,0
20:46:32.839 -> 
20:46:32.872 -> OK
i ilości są obliczane od początku, czyli od at+csq, przy czym liczę od 0.
Użyłem wartość 15-19, wtedy otrzymałem wartość 24,0 , którą przy wysłaniu na serwer odczytuję jako cyfra całkowita.
Także przetestowałem sytuację, gdy wartość otrzymana była mniejsza od 10 i przy mniejszym zakresie niż 15-19, wartość nie wyglądała prawidłowo. Teraz jest OK.
Jeszcze raz dziękuję za pomoc!

@Uzi18 - także dzięki za linka - napewno przyda się przy kolejnym projekcie
ODPOWIEDZ

Strony partnerskie: