• Welcome to LusoRobótica - Robótica em Português.
 

Dúvida em programação Arduino

Started by nadabro, 31 de March de 2011, 15:57

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

nadabro

Boas..

Estou concluindo um projecto em que capturo os dados de uma estação vindos de 433.92Mhz, mas tenho uma dúvidas:

-Converter os dados em letras
Quote
float windd;

(...)

windd = (receivedCode.charAt(23)=='1'?1:0)*256 +
         (receivedCode.charAt(22)=='1'?1:0)*128 +
         (receivedCode.charAt(21)=='1'?1:0)*64 +
         (receivedCode.charAt(20)=='1'?1:0)*32 +
         (receivedCode.charAt(19)=='1'?1:0)*16 +
         (receivedCode.charAt(18)=='1'?1:0)*8 +
         (receivedCode.charAt(17)=='1'?1:0)*4 +
         (receivedCode.charAt(16)=='1'?1:0)*2 +
         (receivedCode.charAt(15)=='1'?1:0);
O receivedCode é uma string, o windd é a direcção do vento, recebo os valores correctos : 0 ou 45º ou 90º, etc...mas queria converter nas letras das rosas dos ventos e fazer Serial.print das letras:

0 --> N
45 -> NE
90 -> E
135 -> SE
180 -> S
225-> SW
270-> W
315-> NW

Encontrei isto noutro código, mas não consigo aplicar no meu..
Quote
{
  "N ", "NE ",
  "E ",  "SE ",
  "S ", "SW ",
  "W ", "NNW"
};


Obrigado


senso

Tens a tua leitura serial que espero que esteja bem feita usando o Serial.avaliable() e tal, então supondo que tens os teus dados na variavel data_in e que vais meter essas letras num array de 4 posições chamado data_out, 4 posições para contar com o terminador , experimenta algo assim:


int num = atoi(data_in);
switch(num){
case 0: data_out = "N\0";
               break;
case 45: data_out = "NE\0";
                 break;
....
case 315: data_out = "NW\0";
                   break;

  default:  data_out = "ERR\0";
                 break;
}

O default é quando o data_in não tem nenhum dos valor esperado, mas podes não colocar nada, depende do que queres fazer, o \0 é o terminador da string, agora é só juntar o resto dos valores.
A função atoi, converte os caracteres ascii recebidos pela porta serial para um inteiro que pode ser muito mais facilmente usado no switch case.
Avr fanboy

nadabro

Ainda sou principiante em programação, o código que estou a usar encontrei na internet, alterei os tempos/protocolo para ser compativel com a minha estação, mas quando se trata de adicionar strings, char, bloqueio. O código ainda ter que ser mt trabalhado, mas é conforme vou aprendendo..

Tenho duas leituras:
-Rain
-WindDirection + Gust

Estas leituras chegam em tempos diferentes: por vezes recebo o "Wind" em intervalos de 30 segundos , outras vezes recebo "Rain" em intervalos de minutos, mas varia, por isso sempre que recebo um pacote RF novo, converto os dados do pacote correspondente e faço Serial.print desse pacote, mas quero que tb faça Serial.print da última leitura do outro pacote.

1º Tenho que definir data_in e data_out se é float, int, etc?
2º Onde insiro o código abaixo? Logo a seguir ao windd = (receivedCode.charAt(23)=='1'?1:0)*256 + ...
3º O Serial.print é o data_out?

Obrigado..


int num = atoi(data_in);
switch(num){
case 0: data_out = "N\0";
               break;
case 45: data_out = "NE\0";
                 break;
case 90: data_out = "E\0";
                    break;
                   
case 135: data_out = "SE\0";
                     break;
case 180: data_out = "S\0";
                       break;
case 225: data_out = "SW\0";
                       break;
case 270: data_out = "W\0";
                       break;
case 315: data_out = "NW\0";
                   break;
}


#define nobits 36
#define initialstring "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define   syncmin   7500
#define   syncmax   9900
#define   separatormin 250
#define   separatormax   750
#define   lowmin   1700
#define   lowmax   2300
#define   highmin   3700
#define   highmax   4300
#define baudspeed 9600
#define receiverpin 2
float windd;
float gust;
float rain;
unsigned long lastReadMills;


void setup() {
pinMode(receiverpin, INPUT);
digitalWrite(receiverpin, HIGH);
Serial.begin(baudspeed);
}


void loop()
{
  String receivedCode = ReceiveCode();

       
           if ((receivedCode.charAt(9)=='1')&&(receivedCode.charAt(10)=='1')&&(receivedCode.charAt(12)=='1')&&(receivedCode.charAt(13)=='1')&&(receivedCode.charAt(14)=='1'))
     {
     
       
        {
      windd = (receivedCode.charAt(23)=='1'?1:0)*256 +
         (receivedCode.charAt(22)=='1'?1:0)*128 +
         (receivedCode.charAt(21)=='1'?1:0)*64 +
         (receivedCode.charAt(20)=='1'?1:0)*32 +
         (receivedCode.charAt(19)=='1'?1:0)*16 +
         (receivedCode.charAt(18)=='1'?1:0)*8 +
         (receivedCode.charAt(17)=='1'?1:0)*4 +
         (receivedCode.charAt(16)=='1'?1:0)*2 +
         (receivedCode.charAt(15)=='1'?1:0);
         
         gust = (receivedCode.charAt(31)=='1'?1:0)*128 +
          (receivedCode.charAt(30)=='1'?1:0)*64 +
          (receivedCode.charAt(29)=='1'?1:0)*32 +
          (receivedCode.charAt(28)=='1'?1:0)*16 +
          (receivedCode.charAt(27)=='1'?1:0)*8 +
          (receivedCode.charAt(26)=='1'?1:0)*4 +
          (receivedCode.charAt(25)=='1'?1:0)*2 +
          (receivedCode.charAt(24)=='1'?1:0);
          gust = gust /5;
          }
         
         
         Serial.println("Wind Direction and Gust");
         Serial.print(windd);
         Serial.println("; ");
         Serial.print(gust *3.6);
         Serial.println("kmh; ");
         Serial.print(rain);
         Serial.println("mm; ");
         Serial.print(lastReadMills/1000);
         Serial.println("s; ");
         Serial.println(" ");
         
       }
                else if ((receivedCode.charAt(9)=='1')&&(receivedCode.charAt(10)=='1')&&(receivedCode.charAt(11)=='0')&&(receivedCode.charAt(12)=='1')&&(receivedCode.charAt(13)=='1')&&(receivedCode.charAt(14)=='0'))
       {
         
               {
        rain = (receivedCode.charAt(31)=='1'?1:0)*32768 +
         (receivedCode.charAt(30)=='1'?1:0)*16384 +
         (receivedCode.charAt(29)=='1'?1:0)*8192 +
         (receivedCode.charAt(28)=='1'?1:0)*4096 +
         (receivedCode.charAt(27)=='1'?1:0)*2048 +
         (receivedCode.charAt(26)=='1'?1:0)*1024 +
         (receivedCode.charAt(25)=='1'?1:0)*512 +
         (receivedCode.charAt(24)=='1'?1:0)*256 +
         (receivedCode.charAt(23)=='1'?1:0)*128 +
         (receivedCode.charAt(22)=='1'?1:0)*64 +
         (receivedCode.charAt(21)=='1'?1:0)*32 +
         (receivedCode.charAt(20)=='1'?1:0)*16 +
         (receivedCode.charAt(19)=='1'?1:0)*8 +
         (receivedCode.charAt(18)=='1'?1:0)*4 +
         (receivedCode.charAt(17)=='1'?1:0)*2 +
         (receivedCode.charAt(16)=='1'?1:0);
        rain = rain/5;
        lastReadMills = millis();
     
     }
     
     
         Serial.println("Wind Direction and Gust");
         Serial.print(windd);
         Serial.println("; ");
         Serial.print(gust *3.6);
         Serial.println("kmh; ");
         Serial.print(rain);
         Serial.println("mm; ");
         Serial.print(lastReadMills/1000);
         Serial.println("s; ");
         Serial.println(" ");
         
        }
}

String ReceiveCode()
{
String receivedCode = initialstring;

(...)}

senso

O data in seria a string onde tens os teus dados, mas como já tens isso em inteiro, usando aquela coisa horrivel com string.charAt, não é horrivel de não ser feio, é horrivel por causa da estupideza de usarem strings no arduino um char[] não lhes chegava -.-
Em vez disto:
int num = atoi(data_in);
switch(num){

metes só switch(windd){
Meter, metes onde achares melhor dentro do loop, pode ser antes de imprimires aquelas coisas por serial.
Avr fanboy

nadabro

Eu sei que o código é horrivel, estou a trabalhar com bits (1,0) escuso de ter Strings, que ocupam mt mais espaço.

Inclusive o código funciona mt bem quando recebo 6 pacotes de 36bits repetidos numa transmissão, mas se receber 2 diferentes repetidos 3x numa transmissão (ab+ab+ab), raramente consigo convert o "b" acho que o código é demasiado lento e não consegue converter.


Já tenho a funcionar, obrigado pela ajuda :)

-mudei "float windd" para "int winddr"
-inseri "char winddr"

alterei ligeiramente o código
                  switch(windd){
case 0: winddr = 'N';
               break;
case 45: winddr = 'NE';
                 break;
case 90: winddr = 'E';
                    break;
                   
case 135: winddr = 'SE';
                     break;
case 180: winddr = 'S';
                       break;
case 225: winddr = 'SW';
                       break;
case 270: winddr = 'W';
                       break;
case 315: winddr = 'NW';
                   break;
}

senso

Avr fanboy

nadabro

Eu sei que sim, mas vou alterar isso no futuro. Queria fazer o seguinte cálculo:

Recebo novos dados de "rain"  e queria subtrair esse valor com a transmissão anterior. O problema é que não sei como guardar os dados da anterior transmissão de forma que esses dados sejam actualizaveis apenas depois do cálculo (rain recente-anterior)..de forma a poder fazer o calculo a partir de novos dados.

Exemplo:

recente: 10
anterior: 5

Serial.print(rain recente)="10"
Serial.print(rain recente-anterior)="5"

...passado uns minutos

recente: 15
anterior: 10

Serial.print(rain recente)="15"
Serial.print(rain recente-anterior)="5


Não sei se estou a explicar bem o que desejo fazer..


senso

Usas uma variavel e metes if (rain_novo != rain_antigo) rain_antigo = rain_novo; acho que é isso que queres.
Avr fanboy

nadabro

Quote from: senso on 01 de April de 2011, 22:14
Usas uma variavel e metes if (rain_novo != rain_antigo) rain_antigo = rain_novo; acho que é isso que queres.

Era isso mesmo que precisava :)

Tem dado imenso jeito, alem do calculo, tem permitido criar condições para ver se a última msg é correcta, etc etc..

Obrigado!