Serial

Hey! Bom... Preciso fazer o seguinte: Pegar uma string através de Serial.read, ler apenas os dois primeiros caracteres, criar uma códição e executar uma função.

O problema é: O serial read recebe o valor em byte, correto? Como converter byte para string, para depois utilizar a função Substring?

Em C puro não existem strings. Uma string é um conjunto (array) de objectos. O problema não está a parecer muito complicado. Pode mostrar o código que já tem?

Na realidade ainda não tenho nada de códigos (fora o básico para usar o Serial.read), meu projeto depende dessas funções. Todas as tentativas que tive foram falhas.

Escrever código assim, é muito fácil (é só chegar ao fórum e pedir)!
De qualquer forma, como aquilo que está a pedir é muito básico, criei este exemplo, baseado neste exemplo aqui:

const int ledPin = 30;

char str[3];
char count = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    str[count++] = Serial.read();
    if (count == 2) {
       str[count] = '\0';
       count = 0;
       if (strcmp(str, "A0") == 0) {
          Serial.println("code OK.");
          digitalWrite(ledPin, HIGH);
       }
       else {
          Serial.println("wrong code.");
          digitalWrite(ledPin, LOW);
       }
    }
  }
}

penso que tem tudo o que pede.

Se tiver dificuldade em perceber o que está feito, diga qualquer coisa.

Esse é o problema... Eu não consigo entender o código!

Passo a passo, então:

char str[3];
char count = 0;
}

São definidas duas variáveis, uma cadeia de caracteres str, com espaço para guardar 3 caracteres e um contador count. A primeira vai guardar a mensagem recebida, a segunda vai guardar a posição onde deve ser guardado o próximo caracter que irá ser recebido.

void loop() {

Esta função chama-se loop (ciclo, em Português), assim ela irá ser repetida (em ciclo) para sempre.

  if (Serial.available()) {

Se hover um caracter disponível para se recebido, é executado o bloco seguinte, isto é, todo o código que está entre o { }.

    str[count++] = Serial.read();

Pega no caracter que está disponível na Serial para ser lido e guarda-o no espaço indicado por count. Ao mesmo tempo, incrementa a variável count, para ficar preparada para o próximo caracter que seja recebido.

    if (count == 2) {

Se já recebeu 2 caracteres, é porque a mensagem já terminou, então vai ter que a "descodificar" (ver o que ele quer dizer). Isso é feito no próximo bloco, portanto entre os caracteres { }.

       str[count] = '\0';
       count = 0;

Estas duas instruções, finalizam o processo de recepção. A primeira acrescenta o caracter especial '\0' no fim da cadeia de caracteres. Este caracter indica em linguagem C, o fim da string. A segunda instrução, prepara o contador para a recepção da próxima mensagem.

       if (strcmp(str, "A0") == 0) {

Esta instrução é a responsável pela comparação de duas cadeias de caracteres. Se duas cadeias de caracteres forem iguais, o resultado da função strcmpé 0. O nome da função é a abreviatura de "string compare".

          Serial.println("code OK.");
          digitalWrite(ledPin, HIGH);
       }

Se as duas strings forem iguais (neste caso fiz a comparação com a string "A0"), então o programa vai fazer qualquer coisa. Neste caso (como era um exemplo simples), estou a ligar um LED e a devolver pela série uma mensagem para que se saiba que a mensagem chegou de forma correcta. E também fechado o bloco de instruções iniciado em if (strcmp(str, "A0") == 0) {.

       else {
          Serial.println("wrong code.");
          digitalWrite(ledPin, LOW);
       }

Caso a mensagem não seja a esperada, neste caso, é feita qualquer coisa também. Assim, desligo o LED, caso ele esteja aceso e envio uma mensagem indicando que a mensagem não foi a correcta. Estas duas instruções estão mais uma vez contidas num bloco, delimitado pelos caracteres { }.

    }
  }
}

São fechados os blocos abertos anteriormente, primeiro o que foi aberto com a instrução if (count == 2) {, seguidamente o que foi aberto na linha if (Serial.available()) { e por último o que foi aberto no início da função void loop() {.

Não sei se desta forma fica claro. Se precisar de mais alguma coisa dia.

Amigo, eu não saberei o tamanho da string à ser recebida. Vou detalhar como funciona. Um software (já está pronto) envia uma rotação/graus para o Arduino, e o Arduino deve girar um motor de passo nos graus informados. (Pode ser que venha 15.5 graus, 20.5, 360.0, etc). Só preciso saber como receber esse valor através de serial, converte-lo para string (o formato vai ser: C1+GRAUS, ex: C1+15.5), poder ler as duas primeiras strings (C1) e pegar o valor (15.5).

Desculpa se não consigo explicar de forma clara, mas da pra entender.

Uma string é um conjunto (array) de objectos

Uma ligeira correçao.Uma string é um vector de caracteres. Usar a palavra objecto é um pouco forte quando estamos a falar em programação.
Quanto tudo ao resto estou de acordo.Desculpa a correçao mas assim para quem lê torna mais claro a tua explicação.
laVie entendeste o mecanismo da coisa?
Entendes-te o que esta a acontecer nesta linha?

str[count++] = Serial.read();

(Pode ser que venha 15.5 graus, 20.5, 360.0, etc). Só preciso saber como receber esse valor através de serial, converte-lo para string (o formato vai ser: C1+GRAUS, ex: C1+15.5), poder ler as duas primeiras strings (C1) e pegar o valor (15.5).

Entao se eu entendi bem o teu soft pode te enviar algo do tipo:
C1+22.5
C2+360.0
É isto?
Se sim entao podes usar o mecanismo que o LuisSilva te disse modificando para o que queres.Tens acesso ao soft que te manda esses dados em termos de codigo?
Se tivesses podias fazer uma struct do lado do soft e envia-la pela serial.Do lado do arduino reconstruias a tua struct com uma union aos bytes que recebeste na serial.Depois era so aceder aos elementos dessa struct no arduino.
Se o teu soft manda esse + podes usa-lo para marcar o CX do resto da mensagem e usar o . para saberes onde termina o valor de graus e as casas decimais.
Algo tipo crias um array com tamanho suficiente para o pior dos cenarios (CX+360.0) com 8 elementos do tipo char.
Depois carregas toda a trama que recebes na serial para esse array e separas os valores olhando para os caracteres "magicos" que sao o + e o .
Procura por maquina de estados ou lê este artigo:

O LuisSilva fez te a papinha toda por tanto é esperado que tu estudes o que ele te passou e não apenas dizeres que nao entendes-te.
Bons estudos

HugoPT:
(...)
Uma ligeira correçao.Uma string é um vector de caracteres. Usar a palavra objecto é um pouco forte quando estamos a falar em programação.
(...)

Concordo completamente. Quando escrevi não reparei e quando reli não gostei como estava. No entanto, penso que, cria maior confusão a alguém que seja entendido e tenha noções de programação e programação orientada a objectos o que penso não ser o caso. Também penso não estar errado, uma vez que se um objecto é uma estrutura com dados e métodos, no fundo um tipo de dados é um objecto sem métodos, não é? (atenção que a minha área não é programação pura, mas sim electrónica, em que a programação é um acessório e não a "coisa em si", no entanto, a minha leitura da situação é esta)

Em relação ao resto:

laVie:
Amigo, eu não saberei o tamanho da string à ser recebida. (...)

Isto é um contradição, uma vez que no primeiro post foi dito:

laVie:
(...) Pegar uma string através de Serial.read, ler apenas os dois primeiros caracteres, criar uma códição e executar uma função.
(...)

Sabendo isto, foi assim que eu fiz a coisa. Não há um enorme problema (ou uma enorme diferença), mas terá de haver algumas alterações. Pode ser feito como sugeriu o HugoPT, pode ser alterado o código do lado do PC para que o processamento seja mais fácil, poderá ser processada a informação no acto da recepção, ou receber a informação e processá-la à posteriori. Mas penso que a sugestão do HugoPT é a mais acertada e segura neste momento.

Sendo assim, a string de recepção tem que ter espaço suficiente para conter todos os caracteres, isto é, deverá ser:

char str[9];

Esta linha, que marcava o fim da string, também não pode ser igual:

    if (count == 2) {

esta talvez seja a parte mais "manhosa" de ser feita, uma vez que não é directa e depende, não do caracter actual, mas do caracter anterior. Por isso, para este efeito a minha sugestão é verificar bem (ou alterar) o código do lado do PC para enviar um caracter de fim de mensagem (como por exemplo um ENTER).

Também me está a parecer que vai ser necessário a conversão da string para um número. Para este efeito há uma "família de funções" atoXXX, que permitem fazer isto (a seguinte converte uma string para inteiro, mas há outras):

A partir daqui, é actuar os motores.

uma vez que se um objecto é uma estrutura com dados e métodos, no fundo um tipo de dados é um objecto sem métodos, não é?

Provavelmente iríamos abrir aqui uma "lata de worms" mas para mim um objecto e tudo aquilo que disseste mas que é construído e alocado em memoria e que la "vive" enquanto não for invocado o seu destrutor, já o mesmo não posso considerar a um tipo de dados.
Já agora és de que área de electrónica?
Eu também fui :slight_smile: a uns anos atrás.
Noto que tens uns conhecimentos consolidados e que pela tua descrição deves saber mais que alguns informáticos :grin:
Bons estudos

Pessoal, eu sou novo nisso e estou achando muito complicado. Não há como apenas converter byte para String? Depois eu só uso um if. Nem que seja byte por byte! Pensei em fazer o código que o Luis passou da seguinte forma:

char str[9];
char count = 0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available())
  {
    str[count++] = Serial.read();
    if(str.substring(2) == "C1" && str.substring(10) == "END")
    {
      //executo a função
    }
  }
}

Adiciono no final da string à ser enviada a palavra "END", e o resto acho que é auto-explicativo... Não há como fazer mais ou menos desta forma?

{É só uma demonstração}

Usares Strings para fazer isso é o caminho errado!
No entanto respondendo tua pergunta:

Não há como apenas converter byte para String?

sim é possível, algo assim

String rawData = "Hello";//String inicial,

void setup()
{
  Serial.begin(9600);
  //if(Serial.available() )String incomingData  =  String(Serial.read()); 
  String incomingData = "World";
  rawData.concat(incomingData); 
 Serial.println(rawData); 
}
void loop()
{
}

Nota que comentei a linha onde podes ver como guardar o byte que te chega pela Serial num String com um cast.
Depois abaixo apenas usei o método concat para concatenar à String rawData outra String que pode ser a que estas a receber da Serie ou apenas a String incomingData.
Tal como te disse acima este método é o errado para o que queres, aprende a usar char arrays correctamente terminados com o carácter '\0' para criares strings.Nota que strings e Strings (com o S maiúsculo) são totalmente diferentes!
Um é um vector de chars correctamente terminado(string) e o outro é um objecto (String)!
Se não entenderes isto pesquisa por ti próprio a explicação, só assim vais aprender e evoluir na tua programação.
Se optares pela solução que para ti parece ser a mais fácil (usares Strings) vais acabar por voltar cá ao fórum de futuro com essa mesma duvida por isso não fujas ao problema e agarra o "toiro pelos cornos".
Bons estudos

Bom, talvez eu tenha pecado na pesquisa antes de criar o tópico... Agora com mais calma, pesquisei novamente e encontrei a solução! O simples código:

int a=1;

char b[2];

String str;

str=String(a);

str.toCharArray(b,2);

Agradeço aos que tentaram me ajudar. E não é fugir do problema, mas sim encontrar uma solução fácil.

Eu ia agora criar outro pequeno exemplo, mas sendo assim poupo o trabalho. Nas últimas semanas tenho estado bastante activo no fórum e há inúmeros posts em que se aconselha que não seja usado o objecto String e que em vez disso sejam usadas as cadeias de caracteres.
Já trabalho há bastantes anos nesta área e tenho utilizado sempre C ou Assembler e não me lembro de nenhuma situação que não tenha conseguido resolver, por isso, se é possível ser feito, há uma solução em C.