LusoRobótica - Robótica em Português
Sistemas específicos => Arduino / AVR => Tópico iniciado por: almamater em 10 de Novembro de 2010, 10:50
-
Olá, como o títlulo do tópico diz.. pode ser uma pergunta parva mas não sei se será possível, tenho os Módulos da Telecontrolli (Transmissor RT4 e Receptor RR3) e queria implementá-los num "robot" e controlar os DC Motors via RF...
De alguma forma é possível enviar valores PWM de um Arduino para outro usando estes módulos RF?
-
Sim, envias numa string e depois fazes a leitura da string e tiras os valores, tens exemplos no playground do arduino.
-
Ah fixe!! uma string equivale ao valor ! não me lembrei de fazer assim.. eu testei os módulos da forma descrita no site Rogercom, em que basicamente envia Hight/Low através do decoder..
Vou ver então como fazer para enviar e receber a string pelo arduino :)
-
Se são serial é só ligar o Tx e o Rx do arduino lá, depois é montar umas strings e usar o itoa para converter de valores numéricos para ascii, ou seja texto, e depois converter de string para valores numericos usando o atoi, procura por itoa avr e atoi avr no google que encontras logo o manual do avr-gcc e de como usar essas funções.
-
Bom a nível de esquemas então não deve ser necessário usar os Encoders/Decoders e deve ser assim:
Transmissor:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg507.imageshack.us%2Fimg507%2F2223%2F002k.th.png&hash=572f40438732e6101020295e0f4cce6041ee2c16) (http://img507.imageshack.us/i/002k.png/)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg543.imageshack.us%2Fimg543%2F7177%2F001j.th.png&hash=fcecbba5f04ad737cd4cecb2fb1ffdc38a461ceb) (http://img543.imageshack.us/i/001j.png/)
Do lado do Transmissor envio usando um conversor Numeros -> Aschii
Do lado do Receptor uso String -> Números
Por exemplo, se quiser transmitir o valor 150, ele converte para o caracter "–" e o transmissor envia "1001 0110" é isto?
-
Convém implementar alguma forma de correcção de erros, para que os valores na recepção sejam fidedignos.
FEC, reed-solomon, são algumas das formas.
É claro que para experiências pode ser feito sem correcçao de erros... mas, para a informação ser bem transmitida, tens mesmo q usar correcção.
-
Convém implementar alguma forma de correcção de erros, para que os valores na recepção sejam fidedignos.
FEC, reed-solomon, são algumas das formas.
É claro que para experiências pode ser feito sem correcçao de erros... mas, para a informação ser bem transmitida, tens mesmo q usar correcção.
agora é que se complicou ::) mas vou ver as formas referidas de correcção :) nem sabia que era necessário héhé mas faz sentido
-
Bom a nível de esquemas então não deve ser necessário usar os Encoders/Decoders e deve ser assim:
Transmissor:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg507.imageshack.us%2Fimg507%2F2223%2F002k.th.png&hash=572f40438732e6101020295e0f4cce6041ee2c16) (http://img507.imageshack.us/i/002k.png/)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg543.imageshack.us%2Fimg543%2F7177%2F001j.th.png&hash=fcecbba5f04ad737cd4cecb2fb1ffdc38a461ceb) (http://img543.imageshack.us/i/001j.png/)
Do lado do Transmissor envio usando um conversor Numeros -> Aschii
Do lado do Receptor uso String -> Números
Por exemplo, se quiser transmitir o valor 150, ele converte para o caracter "–" e o transmissor envia "1001 0110" é isto?
Usa o itoa! se vais simplesmente mandar um numero sem o converter mesmo para ascii vai-te saber mal porque os primeiros 32 caracteres ascii são caracteres de controlo e se os módulos tiverem alguns deles implementados pode não funcionar nada do que queres e depois não sabes porque,
A função itoa do avr-gcc é assim:
itoa(uint8_t pwm, char* buffer, 10); //10 é a base que estamos a usar, 10 para decimal, 2 para binário, 16 para hexadecimal, para nos queremos a base 10
//Para usar, primeiro declarar um buffer para converter de int/char/uint8_t, seja lá o tipo de variavel que for
char buffer[4]; //4 porque são 3 caracteres, um para cada numero mais um caracter para o terminador de string
uint8_t pwm=128; //valor arbitrário do pwm
itoa(pwm, buffer, 10); //agora buffer tem o valor "128'/0' " /0 é o terminador de string
//Para enviar fazes
Serial.print(buffer); // E foi enviado
/*
** Para receber!!!!
*/
char receber[4];
uint8_t pwm_recebido = 0;
while(Serial.available()){
for(int i=0;i<4;i++){
receber[i]=Serial.read(); }
}
pwm_recebido = atoi(receber);
E é basicamente isto, em principio com uns retoques funciona sem problemas, mas atenção que isso é código não compilado nem testado.
-
Obrigado pela explicação,
Em principio tenho de fazer então algo deste tipo, para conseguir depois no Arduino Receptor identificar se o valor de PWM é para a Frente, Trás, Esquerda ou Direita:
char buffer[4];
uint8_t pwm=128;
void setup()
{}
void loop(){
//(...)
itoa(pwm, buffer, 10);
//Frente
Serial.print("F");
Serial.print(buffer);
//Trás
Serial.print("T");
Serial.print(buffer);
//Esquerda
Serial.print("E");
Serial.print(buffer);
//Direita
Serial.print("D");
Serial.print(buffer);
}
-
Não consegui comunicar da maneira que referi acima, no receptor não recebia nada...
Neste momento andei a pesquisar e a ver umas coisas na web e consigo enviar e receber usando a library VirtualWire da seguinte forma:
EMISSOR:
// RF Link using VirtualWire to Transmit messages
// simplex (one-way) receiver with a 315MHz RF Link Transmitter module
#include <VirtualWire.h> // you must download and install the VirtualWire.h to your hardware/libraries folder
#undef int
#undef abs
#undef double
#undef float
#undef round
void setup()
{
// Initialise the IO and ISR
vw_set_ptt_inverted(true); // Required for RF Link module
vw_setup(2000); // Bits per sec
vw_set_tx_pin(1); // pin 1 is used as the transmit data out into the TX Link module, change this to suit your needs.
}
void loop()
{
const char *msg = "ALMAMATER"; // this is your message to send
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait for message to finish
delay(200);
}
RECEPTOR:
// RF Link using VirtualWire to receive messages
// simplex (one-way) receiver with a 315MHz RF Link Receiver module
#include <VirtualWire.h> // you must download and install the VirtualWire.h to your hardware/libraries folder
#undef int
#undef abs
#undef double
#undef float
#undef round
void setup()
{
Serial.begin(9600);
// Initialise the IO and ISR
// vw_set_ptt_inverted(true); // Required for RX Link Module
vw_setup(2000); // Bits per sec
vw_set_rx_pin(1); // We will be receiving on pin 23 (Mega) ie the RX pin from the module connects to this pin.
vw_rx_start(); // Start the receiver
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // check to see if anything has been received
{
int i;
// Message with a good checksum received.
for (i = 0; i < buflen; i++)
{
Serial.print(buf[i]); // the received data is stored in buffer
}
Serial.println("");
}
}
RF com Arduino (http://www.youtube.com/watch?v=keCUImpw_zs#)
Até aqui tudo ok! Depois andei a ver como enviar o valor de PWM juntamente com a instrução (Frente, Tras, Esquerda, Direita) e encontrei este código que parece perfeito para isto:
#include <VirtualWire.h>
typedef struct {
byte command;
char delim;
char buffer [3]; //don't forget to account for the terminator.
}
packet_t;
void rfPacketOut(char commandChar,int data)
{
packet_t packet; // initialize
packet.command = commandChar; //"command char", buf[0] on receiving end
packet.delim = '.'; // "delim char", buf[1] on receiving end
itoa(data, packet.buffer, 10); // turns Integer to ASCII
vw_send((uint8_t *)&packet, sizeof(packet));// Sends packet!
}
#undef int
#undef abs
#undef double
#undef float
#undef round
void setup()
{
Serial.begin(9600); // Debugging only
Serial.println("setup");
// Initialise the IO and ISR
// vw_set_ptt_inverted(true); // Required for RF Link module DR3100
vw_setup(2000); // Bits per sec
vw_set_tx_pin(1); // pin 1
}
void loop()
{
int pwm_valor = 140;
delay(10);
rfPacketOut('A', pwm_valor); // sends "A.140" ?
delay(900);
}
Devia de receber alguma coisa no receptor, mas não sei se estou a usar o código correcto.. usando o referido acima do RECEPTOR não aparece nada, tenho de alterar alguma coisa no código do receptor?
-
Como é que o Virtual wire funciona se é um serial emulado e mais sujeito a erros do que o serial nativo do arduino, provavelmente tinhas ai o Rx trocado com o Tx ou algo assim parecido.
-
Como é que o Virtual wire funciona se é um serial emulado e mais sujeito a erros do que o serial nativo do arduino, provavelmente tinhas ai o Rx trocado com o Tx ou algo assim parecido.
;D héhé funciona.. meti um vídeo no post anterior que mostra o resultado! mas só consigo enviar a frase
-
Como é que o Virtual wire funciona se é um serial emulado e mais sujeito a erros do que o serial nativo do arduino, provavelmente tinhas ai o Rx trocado com o Tx ou algo assim parecido.
Bom, tentei mais vez sem usar a library VirtualWire e não recebo nada a não ser um caracter estranho no serial monitor..
Para envio tenho como teste:
char buffer[4];
uint8_t pwm=128;
void setup() {
Serial.begin(9600);
}
void loop()
{
itoa(pwm, buffer, 10);
Serial.println("E");
Serial.println(buffer);
delay(3000);
}
A receber tenho:
char receber[10];
uint8_t pwm_recebido = 0;
void setup() {
Serial.begin(9600);
}
void loop()
{
if (Serial.available() > 0) {
for(int i=0;i<5;i++){
receber[i]=Serial.read(); }
pwm_recebido = atoi(receber);
Serial.println(pwm_recebido);
}
}
e no receptor ao abrir o Serial Monitor do Arduino a janela não pára de receber coisas (acrescenta linhas) mas não aprecenta nenhuma informação a não ser um caracter de x em x tempo estranho. Será que está a apanhar alguma coisa do meu Router e o caracter diz repeito ao Arduino Emissor!?
-
Não devias usar println, porque ele manda caracteres extra que simbolizam a mudança de linha, esses caracteres podem ser o New Line e/ou Carriage Return.
-
Não devias usar println, porque ele manda caracteres extra que simbolizam a mudança de linha, esses caracteres podem ser o New Line e/ou Carriage Return.
podes sempre fazer
str[strlen-1]='\0';
e depois faz o println, julgo que assim não irá mandar caracteres extra para além do terminador...
Cumprimentos..
-
Bom tenho então de experimentar dessa forma, no entanto com a library VirtualWire já consigo receber e enviar sem problemas, o robot já anda para tras/frente/esquerda/direita o problema agora é mesmo a recepção do sinal pelo receptor que tem de estar a 40cm caso contrário não recebe os comandos do emissor
Pode ser das antenas mas segundo li uns fios de cobre de 17cm chegam.. vou almoçar mas é
-
Bom mal ou bem mas consegui fazer o meu robot andar ;D com library virtualwire ::)
Agora tenho de afinar a InputShield para os valores de PWM variarem conforme a posição do joystick!
A questão da antena e o fraco sinal recebido era devido à alimentação, estava a alimentar tudo a 6v e agora a 9v já ta fixe :)
-
Bom, fiz com a library VirtualWire e deu nisto:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg593.imageshack.us%2Fimg593%2F2954%2Fimg9433.th.png&hash=05aeae610df2defd132757d474add26196f9b79f) (http://img593.imageshack.us/i/img9433.png/)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg338.imageshack.us%2Fimg338%2F8319%2Fimg9429.th.png&hash=3adaa374b914abc8bf5e6bf680c9a7925d80b60b) (http://img338.imageshack.us/i/img9429.png/)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg686.imageshack.us%2Fimg686%2F7211%2Fimg9431.th.png&hash=b0d7ebcd3abc70de73bb478dd081b44815c9aa40) (http://img686.imageshack.us/i/img9431.png/)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fimg18.imageshack.us%2Fimg18%2F4237%2Fimg9432.th.png&hash=e105a553396f5c1d30a9a2df4c005594ef82de13) (http://img18.imageshack.us/i/img9432.png/)
Vídeo de teste:
Arduino RF (http://www.youtube.com/watch?v=onAr4orPLtM#)