substring - error: conversion

Masz problem z Arduino? Tutaj możesz szukać pomocy.
ODPOWIEDZ
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

substring - error: conversion

Post autor: wojciech_69 » 22 kwie 2014, 13:12

Jako że raczkujący ze mnie programista-elektronik proszę o pomoc w kodzie funkcji. Funkcja będzie miała za zadanie wysłania komendy a następnie z odpowiedzi którą otrzyma w postaci:
+CSQ 27,99
OK
wyciąć jak w tym wypadku samą wartość 27 a następnie wyświetlić ją za pomocą Serial.println(wartosc);. Z błędu weryfikacji kodu jaki otrzymuję domniemam, że albo źle zadeklarowałem zmienne albo poprostu źle posługuję się substringiem, oto moja funkcja:
void silasygnalu() {
gsmSerial.println("AT+CSQ=?");
char odczyt = gsmSerial.read();
Serial.println(odczyt);
String wartosc = odczyt;
wartosc = odczyt.substring(6,8);
Serial.println(wartosc);

}

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


macdeez
Młodszy majsterkowicz
Posty: 18
Rejestracja: 25 mar 2014, 22:07

Re: substring - error: conversion

Post autor: macdeez » 22 kwie 2014, 15:39

char odczyt = gsmSerial.read();
char to zmienna znakowa, a z tego co widzę twoja odpowiedź to ciąg znaków czyli zmienna typu string, teraz pytanie co zwraca twoja funkcja ?

poczytaj sobie o tym typie

http://arduino.cc/en/Reference/string
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

Re: substring - error: conversion

Post autor: wojciech_69 » 23 kwie 2014, 08:43

OK, poczytałem ale nie ukrywam, że za wiele to mi nie pomogło. Widziałem tą informację już wcześniej jak również kilka innych. Nie jestem biegły w programowaniu, ale jak zamienię typ zmiennych z np char na string to również otrzymuję błąd.

Może ktoś znalazł bądź przedstawi jakiś przykład jak w bliźniaczej sytuacji można wyjść z problemu.

Obecnie utknąłem w następującym miejscu:

Kod: Zaznacz cały

void silasygnalu() {
  gsmSerial.println("AT+CSQ=?");
  int odczyt = gsmSerial.read();
  Serial.println(odczyt);
  int wartosc = odczyt;
  wartosc = odczyt.substring(6,8);            //' tu wywala blad
  Serial.println(wartosc);
  
 }
Kompilator wywala błąd iż substring nie jest klasą int.

Ps. funkcja ma zwracać odczytaną wartosc.
Awatar użytkownika
wojtekizk
Starszy majsterkowicz
Posty: 311
Rejestracja: 19 lis 2013, 10:54
Lokalizacja: Bydgoszcz

Re: substring - error: conversion

Post autor: wojtekizk » 23 kwie 2014, 21:48

Witam
Kurcze, no nieźle namieszane :-)
Na początek kilka pytań:
1) Czym jest w Twoim programie obiekt gsmSerial?
2) Co ma zwracać w Twoim programie:

Kod: Zaznacz cały

gsmSerial.read();
...a potem będziemy sobie wyjaśniać co dalej :-)
W każdym razie funkcja substring jaka by nie była, działa na zmiennych znakowych (typu char lub string, zależy od biblioteki) i nie będzie działać na 100% na zmiennych typu int :-) Czemu? Bo jest napisana do działania na zmiennych innego typu właśnie :-)
Pozdrawiam
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

Re: substring - error: conversion

Post autor: wojciech_69 » 24 kwie 2014, 08:38

Witam Panie Wojtku. To od początku:
Ad. 1
Obiekt gsmSerial jest oczywiście zadeklarowanym serialem programowym (SoftwareSerial gsmSerial(2,3)).
Ad. 2
gsmSerial ma zwracać odpowiedź z urządzenia na wysłaną wcześniej komendę "AT+CSQ" z której musi zostać wyodrębniona część łańcucha i tak wg podanego wcześniej przykładu, odpowiedz wygląda następująco:
wojciech_69 pisze:+CSQ 27,99
OK
a interesująca mnie wartość w tym wypadku 27.
macdeez
Młodszy majsterkowicz
Posty: 18
Rejestracja: 25 mar 2014, 22:07

Re: substring - error: conversion

Post autor: macdeez » 24 kwie 2014, 09:22

JA bym zrobił to tak :

Kod: Zaznacz cały

void silasygnalu() {
  gsmSerial.println("AT+CSQ=?");
  char odczyt = gsmSerial.read();
  Serial.println(odczyt);
 }

I zobaczysz co ci w ogóle w tym momencie zwraca funkcja qsmSerial i wtedy zastanowimy się jak wydobyć tego liczbę
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

Re: substring - error: conversion

Post autor: wojciech_69 » 24 kwie 2014, 09:59

Tak też zrobiłem w swoim pierwszym poście... Dalej zaczynają się schody, w momencie użycia substring-a.
macdeez
Młodszy majsterkowicz
Posty: 18
Rejestracja: 25 mar 2014, 22:07

Re: substring - error: conversion

Post autor: macdeez » 24 kwie 2014, 12:20

czyli w ekranie serial portu wyświetla ci się to ? +CSQ 27,99 i funkcja zwraca własnie to ? Spróbuj coś takiego :

Kod: Zaznacz cały

void silasygnalu() {
  gsmSerial.println("AT+CSQ=?");
  char odczyt = gsmSerial.read();
  Serial.println(odczyt);
  String stringOne =  String(odczyt); //robimy konwersacje z typu char na typ string 
 string wartoscstring = stringOne.substring(6,8); // funkcaj ta zwaraca dane w stringu ale w postaci napisu czyli jak mamy 'asza' i ja wywolamy od 1,3 to mamy 'sz' ale w stringu 
int wartosc=wartoscstring.toInt() // robimy konwersacje string do int , chociaż jeżeli nie będziesz ich dalej obrabiał to możesz pominąć tą linijkę 
 Serial.println(wartosc);
 }
stringOne.substring(6,8); i tą funkcje wywołaj od 5 do 7 bo pamiętaj że indexy zaczynają się od zera
Chociaż chyba czegoś tu nie rozumiem bo jak w zmiennej char może być więcej niż jeden znak chyba gdzieś mam braki
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

Re: substring - error: conversion

Post autor: wojciech_69 » 25 kwie 2014, 13:23

Kurczę, pojawił się problem. Gdy wrzucę następujący kod:

Kod: Zaznacz cały

#include <SoftwareSerial.h>

SoftwareSerial gsmSerial(2, 3);

const int buttonPin = 4;
int buttonState = 0;

const int ledPin = 13;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  gsmSerial.begin(9600);
  Serial.println("Tu Arduino, witaj...");
}

void loop() {
   buttonState = digitalRead(buttonPin);

   if (buttonState == HIGH) {
    Serial.println("Sprawdzam sile sygnalu.");
    silasygnalu();
    delay(1000);
    Serial.println("Zakonczylem sprawdzanie sily sygnalu");
  }
  else {
    Serial.println("Cos poszlo nie tak ;(");
    digitalWrite(ledPin, LOW);
  }
}

void silasygnalu() {
  digitalWrite(ledPin, HIGH);
  gsmSerial.println("AT");
  delay(1000);
  gsmSerial.println("AT+CSQ");
  delay(1000);
  char odczyt = gsmSerial.read();
  Serial.println(odczyt);
  String stringOne = String(odczyt);
  String wartoscstringOne = stringOne.substring(5,7);
  int wartosc = wartoscstringOne.toInt();
  Serial.println(wartosc);
  digitalWrite(ledPin, LOW);
  delay(500);
}
nawet nie zdążę wcisnąć przycisku a program się zapętla i działa automatycznie bez mojej reakcji. Gdy natomiast zrobię dłuższą przerwę w kodzie i w jej trakcie wcisnę przycisk to oczywiście wykonuje się funkcja silasygnalu() - co eliminuje źle podłączony przycisk (z resztą w jak wrzucę inny program z obsługą przycisku to działa). Aha, arduino wyświetla cały czas:

Kod: Zaznacz cały

Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
.........
Co do samego wyświetlania wyniku funkcji to również nie jest kolorowo ponieważ informacje są wyświetlane w ten sposób:

Kod: Zaznacz cały

Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
.........                                                         // wciskam przycisk
Sprawdzam siłę sygnału.
Zakończyłem sprawdzanie siły sygnału
    O
2
......
Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
Cos poszło nie tak ;(
.........
czyli wygląda na to, jakby arduino nie zdążyło odczytać odpowiedzi urządzenia. W związku z tym może do loop-a
wrzucić:

Kod: Zaznacz cały

if(gsmSerial.available() > 0){
    gsm_char=gsmSerial.read();  
    Serial.print(gsm_char);
albo w tym wypadku zrezygnować w ogóle z tej funkcji i całość wrzucić do loop-a jako że i tak z założenia sprawdzanie sygnału będzie odbywać np co 3 sek. i tym samym arduino będzie non-stop nasłuchiwało odpowiedzi.?
macdeez
Młodszy majsterkowicz
Posty: 18
Rejestracja: 25 mar 2014, 22:07

Re: substring - error: conversion

Post autor: macdeez » 25 kwie 2014, 14:21

Więc tak:

A możesz napisać w jaki sposób jest podłączony ten przycisk ? Bo trochę tego nie rozumiem. Nie widzę deklaracji tego przycisku w pętli setup .

Jeżeli to jest zwykły przycisk podłączany pod pin arduino to musisz go zadeklarować.

czyli dodać do steup:
pinMode(buttonPin ,INPUT);

a co do wyświetlania to tak jak myślałem, zmienia char promuje tylko jeden znak, spróbuj może zadeklarować ja jako string

Kod: Zaznacz cały

void silasygnalu() {
  digitalWrite(ledPin, HIGH);
  gsmSerial.println("AT");
  delay(1000);
  gsmSerial.println("AT+CSQ");
  delay(1000);
 [b]string[/b] odczyt = gsmSerial.read();
  Serial.println(odczyt);
[b]  String stringOne = String(odczyt);[/b][b]//waywalasz tą linijke [/b]
  String wartoscstringOne = stringOne.substring(5,7);
  int wartosc = wartoscstringOne.toInt();
  Serial.println(wartosc);
  digitalWrite(ledPin, LOW);
  delay(500);

Awatar użytkownika
wojtekizk
Starszy majsterkowicz
Posty: 311
Rejestracja: 19 lis 2013, 10:54
Lokalizacja: Bydgoszcz

Re: substring - error: conversion

Post autor: wojtekizk » 25 kwie 2014, 20:16

Witam
hm.....najpierw zacytuje:
Witam Panie Wojtku. To od początku:
Ad. 1
Obiekt gsmSerial jest oczywiście zadeklarowanym serialem programowym (SoftwareSerial gsmSerial(2,3)).
Ad. 2
gsmSerial ma zwracać odpowiedź z urządzenia na wysłaną wcześniej komendę "AT+CSQ" z której musi zostać wyodrębniona część łańcucha i tak wg podanego wcześniej przykładu, odpowiedz wygląda następująco:
wojciech_69 napisał(a):
+CSQ 27,99
OK

a interesująca mnie wartość w tym wypadku 27.
... i teraz pytanie ...czy aby na pewno odpowiedź jest taka?:

Kod: Zaznacz cały

+CSQ 27,99 
OK
... czy może taką chciałbyś otrzymać? Bo widzisz funkcja read() dla obiektów klasy SoftwareSerial zwraca wartość typu Integer, czyli pojedynczą liczbę, więc nie wydaje mi się aby zwracała Ci ciąg:"+CSQ 27,99" podczas pojedynczego wywołania w Twojej funkcji silasygnalu() :-)
Pozdrawiam
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

Re: substring - error: conversion

Post autor: wojciech_69 » 27 kwie 2014, 10:38

Krapi, dzięki za odpowiedz w temacie. Przeanalizuję podsunięty przez Ciebie kod. Co do odpowiedzi jaką zwraca mi Arduino to zmodyfikowałem trochę kod (usunąłem przycisk z którym miałem dziwny problem) i ustawiłem aktywację funkcji poprzez wysłanie obojętnie jakiego znaku na konsolę. Teraz wygląda tak:

Kod: Zaznacz cały

#include <SoftwareSerial.h>

SoftwareSerial gsmSerial(2, 3);

char znak_serial = 0;
char znak_gsmSerial = 0;

void setup() {
  Serial.begin(9600);
  gsmSerial.begin(9600);
  Serial.println("Tu Arduino, witaj...");
}

void loop() {
  if (gsmSerial.available() > 0) {
    znak_gsmSerial = gsmSerial.read();
    Serial.println(znak_gsmSerial);
  }
  if (Serial.available() > 0) {
    znak_serial = Serial.read();
    Serial.println(znak_serial);
    Serial.println("Sprawdzam sile sygnalu.");
    silasygnalu();
    Serial.println("Zakonczylem sprawdzanie sily sygnalu");
  }
}

void silasygnalu() {
  gsmSerial.println("AT");
  delay(1000);
  gsmSerial.println("AT+CSQ");
  delay(1000);
  char odczyt = gsmSerial.read();
  Serial.println(odczyt);
  String stringOne = String(odczyt);
  String wartoscstringOne = stringOne.substring(5,7);
  int wartosc = wartoscstringOne.toInt();
  Serial.println(wartosc);
  delay(500);
}


i zwraca taką wartość:

Kod: Zaznacz cały

Tu Arduino, witaj...
q
Sprawdzam sile sygnalu.
A
0
Zakonczylem sprawdzanie sily sygnalu
T






O
K




A
T
+
C
S
Q






+
C
S
Q
:
 
2
5
,
9
9








O
K




Czyli sama funkcja nie odczytuje otrzymanych znaków i nie "obrabia" ich, tylko robi to w loopie

Kod: Zaznacz cały

if (gsmSerial.available() > 0) {
    znak_gsmSerial = gsmSerial.read();
    Serial.println(znak_gsmSerial);
  }
No nic, siadam i kombinuję dalej... :)

Ps. w powyższym przypadku, interesująca mnie wartość to oczywiście: 25.
Awatar użytkownika
wojtekizk
Starszy majsterkowicz
Posty: 311
Rejestracja: 19 lis 2013, 10:54
Lokalizacja: Bydgoszcz

Re: substring - error: conversion

Post autor: wojtekizk » 27 kwie 2014, 12:59

Witam
no widac postępy.... a po co siadać i kombinować... zobacz to, co prawda na samym Serialu ..ale da Ci wskazówkę :-)

Kod: Zaznacz cały

void setup()
{
Serial.begin(9600);
}
void loop()
{
  char znak;
  String s="";
  while (Serial.available() > 0) 
  {
    znak = Serial.read();
    s+=znak;
  }
  if(s!=""){Serial.println(s.substring(5,7));delay(100);Serial.flush();}
}
Pozdrawiam
wojciech_69
Młodszy majsterkowicz
Posty: 36
Rejestracja: 30 gru 2013, 14:28

Re: substring - error: conversion

Post autor: wojciech_69 » 28 kwie 2014, 18:03

OK, zastosowałem Wasze porady w następujący sposób:

Kod: Zaznacz cały

#include <SoftwareSerial.h>

SoftwareSerial gsmSerial(2, 3);

char znak_serial = 0;
char znak_gsmSerial;
String s="";

void setup() {
  Serial.begin(9600);
  gsmSerial.begin(9600);
  Serial.println("Tu Arduino, witaj...");
}

void loop() {
  while (gsmSerial.available() > 0) {
    znak_gsmSerial = gsmSerial.read();
    s += znak_gsmSerial;
  }
  if (s !="") {
    Serial.println(s.substring(24,26));
    delay(100);
    Serial.flush();
  }
  if (Serial.available() > 0) {
    znak_serial = Serial.read();
    Serial.println(znak_serial);
    Serial.println("Sprawdzam sile sygnalu.");
    silasygnalu();
    Serial.println("Zakonczylem sprawdzanie sily sygnalu");
  }
}

void silasygnalu() {
  gsmSerial.println("AT");
  delay(1000);
  gsmSerial.println("AT+CSQ");
  delay(1000);
}
natomiast Arduino zwraca:

Kod: Zaznacz cały

Tu Arduino, witaj...
q
Sprawdzam sile sygnalu.
Zakonczylem sprawdzanie sily sygnalu
26
26
26
26
26
26
26
26
26
26
26
26
26

......
Czyli wyświetla to o co walczyłem ;) jednak zapętla się i dopóki nie nacisnę resetu na płytce, działa w nieskończoność.

1. Czy powodem tego może być 2-gi "if" z serialem który powoduje powyższe zapętlenie?

2. Jaką funkcję pełni Serial.flush()? (na arduino.cc oprócz tego iż bodajże czeka na koniec transmisji i czyści bufor to nic innego nie znalazłem?)

3. Kolejnym problemem będzie fakt iż teraz w zależności od wartości liczbowej która zostanie mi zwrócona będę chciał zrobić kilka if-ów które będą wyświetlały odpowiednie informacje, np jeżeli odpowiedź będzie w przedziale 25-27 wtedy wyświetlę: "siła sygnału ok 80%" itp. W związku z tym czy nie lepiej tego wszystkiego zamknąć w funkcji silasygnalu() by nie zaśmiecać loop-a 10-ma if-ami, czy pod względem parametrów obliczeniowych arduino/czasu wykonania programu/zasad programowania jest to bez znaczenia (lub nieuniknione pod względem działania)?
Awatar użytkownika
wojtekizk
Starszy majsterkowicz
Posty: 311
Rejestracja: 19 lis 2013, 10:54
Lokalizacja: Bydgoszcz

Re: substring - error: conversion

Post autor: wojtekizk » 28 kwie 2014, 20:01

Witam...
Cóż trudno odpowiedzieć na Twoje pytania bez testowania kodu...Powszechnie znane są problemy z synchronizacją danych jakie wyświetla nam funkcja Serial.println. Po prostu port szeregowy nie jest w żaden sposób zsynchronizowany w taktowaniem procesora, a to oznacza, że nie ma żadnej gwarancji że w kodzie odpowiednie wyświetlanie danych będzie przebiegało w takiej kolejności, jak sobie tego życzymy, niestety...
Trzeba kod testować, a to z kolei oznacza, że dla testów bezpiecznie jest dać po każdym zastosowaniu funkcji Serial, gsmSerial itd. jakieś rozsądnej funkcji delay, np. delay(1500) aby mieć szansę odczytania tego co wypluje Serial. Po drugie chyba także w gsmSerial jest funkcja flush, (trzeba sprawdzić w bibliotece)... zobacz może warto ją zastosować.

Co do wyświetlania bez końca, to tak niestety jest, w końcu loop to "neverending story" :-). Aby temu zapobiec jest kilka metod. Ta najprostsza to zapamiętanie w zmiennej poprzedniego odczytu i wyświetlanie w Serialu tylko wtedy, gdy aktualna wartość różni się od poprzedniej.

Co do zaśmiecania loopa to jak najbardziej trzeba się starać robić wszystko w funkcjach zewnętrznych, ale także bez zbytniej przesady. Dlaczego? Bo jeśli najważniejsza jest szybkość wykonywania kodu, to nie ma czasu na wywoływanie funkcji. Każdy takt procesora, nawet tego RISC-owego jest na wagę złota :-)
Pozdrawiam
ODPOWIEDZ

Strony partnerskie: