LusoRobótica - Robótica em Português
Sistemas específicos => Arduino / AVR => Tópico iniciado por: FCarvalho5555 em 08 de Abril de 2014, 11:04
-
Boas pessoal,
Quero enviar uma trama de 4 Bytes para o arduino [coordenadorID, sensorID, comando, fim] mas estou com uns problemas.
Envio da trama:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fi61.tinypic.com%2Faxfyo8.png&hash=8a751cb8e94f64f0e2bf2f01f74960226dbc7d3b)
O que o arduino vê:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fi60.tinypic.com%2F717hi8.png&hash=f79c4e301b5268d839d83e1fb3acf965cef12a9f)
O 0x61 0x62 0x63 0x66 estão correctos, não percebo é porque que aparecem aqueles 0xFF todos.
byte idCoordenador = 0x61;
byte myID = 0x62;
byte fimTrama = 0x66;
byte trama[4];
void setup(){
Serial.begin(9600);
}
void loop(){
if(Serial.available()){
for(int i = 0; i < sizeof(trama); i++){
trama[i] = Serial.read();
}
for(int i = 0; i < sizeof(trama); i++){
Serial.print(trama[i], HEX);
}
}
}
-
Porque testas uma só vez o serial available.
Tens de testar para cada byte que sacas.
Edit: corrigir ortografia
-
Se o tipo byte tiver realmente só 1 byte de tamanho, esses FF é um "problema" do Serial.print na conversão para HEX . Experimenta Serial.print(trama[ i], DEC) para veres se não aparece 97989...
-
Já troquei para DEC e aparece o seguinte:
972552552559825525525599255255255102255255255
-
Tens de fazer sempre serial.available cada vez que fazes uma leitura.
-
Faz lá
Serial.print(sizeof(byte), DEC);
Serial.println("");
e reporta o valor.
-
O senso e eu já demos a solução.
O problema não é do print, é do código.
-
int HardwareSerial::read(void)
{
// if the head isn't ahead of the tail, we don't have any characters
if (_rx_buffer->head == _rx_buffer->tail) {
return -1;
} else {
unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
_rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE;
return c;
}
}
-1 numa variavel unsigned de 8 bits dá que valor?
0xFF
Portanto, é usar o available ver que valor retorna e ler só e apenas o numero de caracters que estão disponiveis, é para isso mesmo que o available existe.
-
O senso e eu já demos a solução.
O problema não é do print, é do código.
Exacto, o erro está no código. Tens que fazer algo deste genero:
uint8_t size = 4;
uint8_t bytesRead = 0;
byte trama[size];
void setup(){
Serial.begin(9600);
}
void loop(){
if(Serial.available()){
trama[bytesRead] = Serial.read();
bytesRead++;
if(bytesRead==4){
for(int i = 0; i < size; i++)
Serial.print(trama[i], HEX);
bytesRead = 0;
}
}
}
Quando fazes o Serial.read() ele devolve o valor recebido e limpa o buffer e só o carrega quando fazes Serial.available().
Nota: o código feito aqui no post por isso é provável que não funciona assim directo.
-
Ah, pois é, é do available() . Tava a ver 4 "bytes" e isso tava a levar-me a pensar que podia ser do tamanho do tipo de dados, duh.
-
Com o código do metro consigo detectar a trama correctamente :)
Só que agora queria evoluir mais um bocado e estou com outro problema.
Quero enviar dois tipos de tramas:
Trama comando
Tamanho: 5 bytes
Cada campo corresponde a 1 byte
Campos: Tipo(0x21) | Origem | Destino | Comando | Fim(0x66)
Trama valores
Tamanho: 7 bytes
Cada campo corresponde a 1 byte
Campos: Tipo(0x23) | Origem | Destino | Valor1 | Valor2 | Valor3 | Fim(0x66)
O meu problema é que quando mando qualquer uma das tramas a primeira vez não tenho problema (Imprime que a trama x foi recebida), mas depois tento enviar de novo e já não funciona, ou seja, apenas funciona a primeira vez.
byte tramaComando[5];
byte tramaValores[7];
int byteCounter = 0;
boolean flagComando = 0, flagValores = 0;
byte byteRead;
void setup(){
Serial.begin(9600);
}
void loop(){
if(Serial.available()){
byteRead = Serial.read();
if(byteRead == 0x21 && byteCounter == 0)
flagComando = 1;
else if(byteRead == 0x23 && byteCounter == 0)
flagValores = 1;
if(flagComando)
tramaComando[byteCounter] = byteRead;
else if(flagValores)
tramaValores[byteCounter] = byteRead;
byteCounter++;
if(flagComando && byteCounter == 4){
Serial.println("Trama comando recebida");
flagComando = 0;
byteCounter = 0;
}
else if(flagValores && byteCounter == 7){
Serial.println("Trama valores recebida");
flagValores = 0;
byteCounter = 0;
}
}
}
-
faz um print do byteread e dos valores das flags para cada serial.read(). envia duas vezes a trama e coloca aqui o log
-
Detetei alguns erros no código:
1º
A trama comando é de 5 bytes e não 4 (segundo a tua especificação):
if(flagComando && byteCounter == 4){
2º erro (e que causa o comportamento que vês se enviares uma trama de comando, por causa do 1º erro):
O código não está preparado para o primeiro byte a receber não ser comando ou valores (0x21 ou 0x23). Quando o primeiro byte que recebes é diferente, incrementas o byteCounter na mesma e ficas num estado sem saída.
Se mudares o:
byteCounter++;
para:
if(flagComando || flagValores) byteCounter++;
deve resolver.
-
Com a ajuda do jm_araujo o código já está a funcionar :)
Vou aproveitar e tirar mais uma dúvida, se eu quiser limpar o buffer da porta serie e visto que a função Serial.flush() foi alterado posso utilizar o seguinte código ?
void limpaBuffer(){
while(Serial.available() > 0){
lixo = Serial.read();
}
}
-
Mais uma dúvida, será possível pegar no inteiro que a função analogRead() devolve e passar aquilo para um byte (8 bits), visto também que a resolução da ADC do arduino é de 10bits
-
uint8_t adc8bits = analogRead(canal) >> 2;
O >>2 é um shift right de 2 bits, o que isto quer dizer é que move o valor de 10 bits duas casas para o lado direito, ficando assim com 8 bits.
-
Ao fazer esta operação apenas vou perde resolução da minha ADC, ou seja, a ler o valor de determinado sensor o meu resultado não vai ser tão aproximado do real, correto?
-
Sim passas a ter um valor no intervalo [0, 255] em vez do intervalo [0, 1023].
Aquele bit shift de duas casas matemáticamente é o mesmo que dividir o valor por 4 e ignorar as casas decimais.