Tenho um sensor que após enviar enviar 3 bytes pela porta serial (B0, 31,E1) ele me responde com 8 bytes : Sendo os 2 primeiros (B0 e A2) fixos e identificadores. O terceiro byte é o que vai definir o tipo de unidade. (pode ser 00, 01, 02, e 03) . Normalmente será 02 significando unidade em quilogramas). Em seguida é que vem o complicado. São 4 bytes significando o valor como um inteiro de 32 bits . O ultimo byte é o checksum que é a soma de todos os bytes anteriores.
O que não sei é como capturar esses 8 bytes , e ler o valores e fazer essa conversão para decimal ... Agradeceria se alguém puder me dar uma luz.
Olá,
Por curiosidade, que tipo de sensor é?
Então, a primeira coisa a fazer é verificar no ciclo principal se existem dados disponíveis no buffer de recepção do porto série e fazer uma função para processar esses dados.
Por exemplo:
// Verifica se existem dados disponiveis.
if ( Serial.available() ) {
dados_recebe();
}
Agora basta fazer a função dados_recebe() utilizando a função Serial.readBytes(). O timeout para a recepção de dados pode ser alterado, por exemplo no setup(), através de Serial.setTimeout(). Por omissão o timeout é de 1000 milisegundos.
Depois da recepção dos dados podes validar a mensagem verificando se tem 8 bytes e o respectivo checksum.
Exemplo onde antes de obter o inteiro de 32 bits é feita a verificação do tamanho da mensagem e validado o checksum:
// Definicao dos indices (idx) da mensagem recebida (8 bytes).
// (apenas para facilitar...)
#define IDX_ID_1 0
#define IDX_ID_0 1
#define IDX_TYPE 2
#define IDX_INT32_3 3
#define IDX_INT32_2 4
#define IDX_INT32_1 5
#define IDX_INT32_0 6
#define IDX_CHKSUM 7
// Definicao do tamanho do buffer auxiliar de recepcao.
#define SIZE_BUFFER 50
// Buffer auxiliar para processar os dados recebidos.
unsigned char rx_buffer[SIZE_BUFFER];
void dados_recebe() {
long resultado;
int rx_len;
unsigned char chksum=0;
// Obtem os dados para o buffer:
rx_len = Serial.readBytes(rx_buffer, SIZE_BUFFER);
// Mostra os dados obtidos.
Serial.print("Dados recebidos: ");
for(int i = 0; i < rx_len; i++) {
if ( (rx_len == 8) && (i < IDX_CHKSUM) ) {
// Soma cada byte para uma variavel de um byte.
// A soma irá exceder o byte... o excesso será descartado...
chksum += rx_buffer[i];
}
// Mostra os dados da mensagem em hexadecimal.
Serial.print(" 0x");
Serial.print(rx_buffer[i], HEX);
}
// Verificacao do checksum.
// Ignorar a mensagem se esta tiver mais de 8 bytes...
if (rx_len == 8) {
Serial.print(" Checksum: ");
Serial.print(chksum, HEX);
// Se o checksum coincide:
if (chksum == rx_buffer[IDX_CHKSUM]) {
Serial.print(" OK!");
// Obtem o numero a partir dos 4 bytes,
// assumindo que o primeiro e' o mair peso
// e o ultimo o de menor peso.
// Aqui o valor é construído usando a soma dos bytes
// de maior peso deslocados para a esquerda.
// O ultimo nao precisa, sera apenas adicionado.
// Caso o inteiro seja enviado pela ordem inversa
// entao basta fazer o mesmo mas comecar pelo IDX_INT32_0
// em vez do IDX_INT32_3.
resultado = ((long)rx_buffer[IDX_INT32_3] << 24) +\
((long)rx_buffer[IDX_INT32_2] << 16) +\
((long)rx_buffer[IDX_INT32_1] << 8) +\
rx_buffer[IDX_INT32_0];
Serial.print(" Valor inteiro obtido: ");
Serial.print(resultado);
if (rx_buffer[IDX_TYPE] == 2) {
Serial.print(" kg.");
} // else if ... testar os outros casos...
} else {
Serial.print(" ERRO!");
}
}
Serial.println(" ");
}
Obrigado peja ajuda amigo. Vou testar o código. O sensor é o HX-750 para células de carga. Veja no seguinte link: HX-750
O código está capturando os dados porém imprime na mesma linha duas respostas consecutivas e não detecta o checksum para passar para a etapa seguinte. O inicio correto de cada mensagem são os 2 bytes : 0xB0 0xA2.
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x3 0xC8 0xED 0xC 0xB0 0xA2 0x2 0x0 0x3 0xCA 0xB9 0xDA
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x3 0x8C 0xC3 0xA6 0xB0 0xA2 0x2 0x0 0x3 0xBB
0x75 0x87
Coloquei a variavel resultado como unsigned long . Tirei qualquer delay do loop e agora obtenho o seguinte:
Dados recebidos: 0xB0 0xA2 0x2 0x0 0xB0 0xA2 0x2 0x0 0xB0 0xA2 0x2 0x0 0x3 0xA3 0x36 0x30
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x3 0xA6 0xCE 0xCB Checksum: CB OK! Valor inteiro obtido: 239310 kg.
Dados recebidos: 0xB0 0xA2 0x2 0x0 0xB0 0xA2 0x2 0x0 0xB0 0xA2 0x2 0x0 0x3 0x98 0x70 0x5F
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x3 0xBD 0x41 0x55 Checksum: 55 OK! Valor inteiro obtido: 245057 kg.
Como se vê a medição ocorre ocasionalmente e parece coerente mas só estou obtendo leituras em cerca de 1Hz.... não há nenhum delay especificado no código. Já verifiquei que o sensor suporta uma taxa de atualização bem maior.
Consegui uma melhora :
diminui o #define SIZE_BUFFER 50 para 8 e parece que acelerou muito a saida. Colocando o delay (100) está funcionando perfeitamente:
Também dividi o resultado por 100000:
Serial.print(resultado/100000);
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x5 0x5F 0xB7 0x6F Checksum: 6F OK! Valor inteiro obtido: 3 kg.
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x5 0x5F 0xB7 0x6F Checksum: 6F OK! Valor inteiro obtido: 3 kg.
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x5 0x3C 0xB2 0x47 Checksum: 47 OK! Valor inteiro obtido: 3 kg.
Dados recebidos: 0xB0 0xA2 0x2 0x0 0x5 0x44 0xC7 0x64 Checksum: 64 OK! Valor inteiro obtido: 3 kg.
Então agora parece bem correto.
A função de leitura de bytes só termina quando o buffer auxiliar de recepção ficar cheio ou quando acontecer o timeout (que por omissão é 1 segundo).
O timeout pode ser alterado através a função Serial.setTimeout().
Exemplo de acerto do timeout (no setup()) para 50 ms:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.setTimeout(50);
}
Neste caso reduzindo o buffer para 8 bytes resolve a situação
. Geralmente nestas situações uso um buffer maior que o tamanho da mensagem porque por vezes pode surgir algum(s) byte(s) a mais no inicio ou no fim da mensagem (que após análise da mensagem poderiam ser descartados/ignorados). Com o um buffer auxiliar de recepção maior que a mensagem, o acerto do timeout resolve a situação
.
Excelente . Obrigado tinyelectr ! O seu código me ajudou muito !!!
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.