collapse

* Links de Robótica

* Posts Recentes

Qual tipo de soldar e temp indicados? por edeweld
[Hoje às 01:46]


Sensor de corrente AC - alternativas? por senso
[Ontem às 20:42]


The latest "nightmare inducing" Boston Dynamics robots por LVirtual
[Ontem às 14:39]


Fonte avariada Delta por jm_araujo
[Ontem às 10:48]


"Direitos Humanos" para robôs... por LVirtual
[Ontem às 08:05]


Encomenda Colectiva à Farnell por Hugu
[20 de Fevereiro de 2017, 22:55]


Estação de Soldar Parkside PLS 48 B1 por Hugu
[20 de Fevereiro de 2017, 18:51]


Encomenda à PCBWay por Hugu
[20 de Fevereiro de 2017, 01:20]


Printer 3D barata por tiagoxefe
[19 de Fevereiro de 2017, 17:12]


Métodos de protecção dos circuitos electrónicos por KammutierSpule
[18 de Fevereiro de 2017, 23:27]

Autor Tópico: Ler PPM com Arduino  (Lida 4052 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline dvdt

  • Mini Robot
  • *
  • Mensagens: 1.228
  • David_@@@_Teles
Ler PPM com Arduino
« em: 04 de Novembro de 2012, 15:25 »
Boas pessoal eu estou aqui com uma duvida
Estou a escrever o código para o meu novo projecto e precisava da vossa ajuda para me dizerem o que devo fazer para ler o sinal ppm do receptor rc e para os enviar novamente através do arduino, ou seja ler e inserir a mesma leitura. Sim de momento pode parecer sem sentido mas eu vou vos deixar um cheirinho de como vai funcionar.
Quando o botão do comando estiver numa posição o arduino vai enviar os sinais que esta a receber e quando estiver noutra posição vai se dirigir para waypoints
David Teles

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.100
  • Helpdesk do sitio
Re: Novo veiculo
« Responder #1 em: 04 de Novembro de 2012, 15:29 »
Vai ver código dos mil e um projectos de quad-copter que existem, todos recebem dados PPM RC e 99% enviada dados PPM para os ESC's.
Avr fanboy

Offline dvdt

  • Mini Robot
  • *
  • Mensagens: 1.228
  • David_@@@_Teles
Re: Novo veiculo
« Responder #2 em: 04 de Novembro de 2012, 15:47 »
eu estava a pensar em usar ch1=pulseIn() para obter o valor em microsegundos e depois writeMicroseconds(ch1)
Acham que resulta?
David Teles

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.100
  • Helpdesk do sitio
Re: Novo veiculo
« Responder #3 em: 04 de Novembro de 2012, 15:52 »
O pulseIn é uma função bloqueante, ou seja estás a perder tempo á espera que o sinal mude de estado, a maneira mais inteligente de fazer isso é usar interrupções, todos os pinos do atmega podem gerar uma interrupção.
Avr fanboy

Offline dvdt

  • Mini Robot
  • *
  • Mensagens: 1.228
  • David_@@@_Teles
Re: Novo veiculo
« Responder #4 em: 04 de Novembro de 2012, 15:55 »
Pois mas tenho pouca pratica com o arduino e nunca usei interropçoes
David Teles

Offline amando96

  • Mini Robot
  • *
  • Mensagens: 1.627
  • MAC address? But I have windows...
    • Projects, News, Blog, Tutorials
Re: Ler PPM com Arduino
« Responder #5 em: 04 de Novembro de 2012, 16:53 »
Aproveita para aprender  :P literatura sobre o tema não falta.

O que tenho agora também está a usar pulsein, mas é para refazer quando houver tempo  :)

StarRider

  • Visitante
Re: Ler PPM com Arduino
« Responder #6 em: 04 de Novembro de 2012, 19:39 »
Boas,

É quando se chega a estes requisitos que saltam à vista as fragilidades do "compilador" Arduino, e digo
"compilador" pois o Arduino não passa disso ... felizmente o hardware "por baixo" do Arduino (seja ele AVR
ou outro) tem sempre a possibilidade de fazer o tu queres muito facilmente.

Se decidires meter "esse tal" Arduino de lado e programar com uma verdadeira toolchain tenho aqui código
para ler PPM e PCM que podes usar sem qualquer problema.

Abraços,
PA

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.715
Re: Ler PPM com Arduino
« Responder #7 em: 04 de Novembro de 2012, 19:44 »
Se decidires meter "esse tal" Arduino de lado e programar com uma verdadeira toolchain tenho aqui código
para ler PPM e PCM que podes usar sem qualquer problema.

Abraços,
PA

ele até pode misturar as duas se tiveres a usar o avr-gcc.

Offline dvdt

  • Mini Robot
  • *
  • Mensagens: 1.228
  • David_@@@_Teles
Re: Ler PPM com Arduino
« Responder #8 em: 04 de Novembro de 2012, 19:46 »
Mas será que alguem me podia explicar mais ao menos  como é que funciona a funçao interrupt() e como é que posso usá-la (por ex. codigo para o quad que falaram)
David Teles

Offline dvdt

  • Mini Robot
  • *
  • Mensagens: 1.228
  • David_@@@_Teles
Re: Ler PPM com Arduino
« Responder #9 em: 04 de Novembro de 2012, 21:06 »
Boas agora precisava de saber é como é que meto a função if a apanhar toda a função do gps e que variáveis vou usar  para os sinais ppm. Em baixo fica o código em já contam as variveis (ch1,ch2,ch3) bem como as inputs do recetor.
Código: [Seleccione]
#include <Servo.h>
#include <NewSoftSerial.h>
#include <TinyGPS.h> 
#include <Wire.h>
#define speedesc 125
int ch1;
int ch2;
int ch3;
int reverse=0;
int HMC6352Address = 0x42;
int slaveAddress;
byte headingData[2];
int i, headingValue;
  float flat, flon;
   float heading=0;
int headinggps;
int buzzing;
int buttonreaddone;
Servo servo;
Servo esc;
TinyGPS gps;
NewSoftSerial nss(8, 11);
#define buzzer 7
int radius;
int x4=0;
#define buttons 0
int waypoints;
int waycont=1;
float x2lat;
float x2lon;
float flat2;
float flon2;
float flat3;       
float flon3;
float flat4;
float flon4;
float flat5;
float flon5;
float flat6;
float flon6;
float flat7;
float flon7;
float flat8;
float flon8;
float flat9;
float flon9;
float flat10;
float flon10;
float flat11;
float flon11;
float flat12;
float flon12;
float flat13;
float flon13;
void gpsdump(TinyGPS &gps);
bool feedgps();
void printFloat(double f, int digits = 2);
int serv;
void setup()
{
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  slaveAddress = HMC6352Address >> 1; 
Wire.begin();
  Serial.begin(115200);
  nss.begin(4800);
  pinMode(buzzer, OUTPUT);
  pinMode(buttons, INPUT);
servo.attach(9);
esc.attach(10);
esc.write(90);
delay(5000);
buzz();
  ch1 = pulseIn(5, HIGH, 25000);
  ch2 = pulseIn(6, HIGH, 25000);
  ch3 = pulseIn(7, HIGH, 25000);
 
}
void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  while (millis() - start < 250)
  {
    if (feedgps())
      newdata = true;
  }
 
  if (newdata)
  {
    Serial.println("Acquired Data");
    Serial.println("-------------");
    gpsdump(gps);
    Serial.println("-------------");
   Serial.println();
  }
}

void printFloat(double number, int digits)
{

  if (number < 0.0)
  {
     Serial.print('-');
     number = -number;
  }


  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
 
  number += rounding;


  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
 Serial.print(int_part);


  if (digits > 0)
    Serial.print(".");

  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint;
  }
}

void gpsdump(TinyGPS &gps)
{
  long lat, lon;

  unsigned long age, date, time, chars;

  unsigned short sentences, failed;

 
  feedgps();

  gps.f_get_position(&flat, &flon, &age);
  Serial.print("Lat/Long(float): "); printFloat(flat, 7); Serial.print(", "); printFloat(flon, 7);
  Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
feedgps();

  gps.stats(&chars, &sentences, &failed);
  Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed);
  if(buttonreaddone!=5){
    buttonread();
  }
  if(buttonreaddone==5){
distance();
  }
}
 
bool feedgps()
{
  while (nss.available())
  {
    if (gps.encode(nss.read()))
      return true;
  }
  return false;
}

void distance(){
  if(waycont==1){
 x2lat = flat2;
 x2lon = flon2;   
  }
  if(waycont==2){
    x2lat = flat3;
    x2lon = flon3;
  }
  if(waycont==3){
    x2lat = flat4;
    x2lon = flon4;
  }
  if(waycont==4){
  x2lat = flat5;
  x2lon = flon5;
  }
   if(waycont==5){
  x2lat = flat6;
  x2lon = flon6;
  }
    if(waycont==6){
  x2lat = flat7;
  x2lon = flon7;
  }
     if(waycont==7){
  x2lat = flat8;
  x2lon = flon8;
  }
     if(waycont==8){
  x2lat = flat9;
  x2lon = flon9;
  }
     if(waycont==9){
  x2lat = flat10;
  x2lon = flon10;
  }
     if(waycont==10){
  x2lat = flat11;
  x2lon = flon11;
  }
     if(waycont==11){
  x2lat = flat12;
  x2lon = flon12;
  }
     if(waycont==12){
  x2lat = flat13;
  x2lon = flon13;
  }
 

 float flat1=flat;           
 float flon1=flon;
float dist_calc=0;
float dist_calc2=0;
float diflat=0;
float diflon=0;


diflat=radians(x2lat-flat1);
flat1=radians(flat1);
x2lat=radians(x2lat);
diflon=radians((x2lon)-(flon1));

dist_calc = (sin(diflat/2.0)*sin(diflat/2.0));
dist_calc2= cos(flat1);
dist_calc2*=cos(x2lat);
dist_calc2*=sin(diflon/2.0);                                       
dist_calc2*=sin(diflon/2.0);
dist_calc +=dist_calc2;

dist_calc=(2*atan2(sqrt(dist_calc),sqrt(1.0-dist_calc)));

dist_calc*=6371000.0;
Serial.println("distance");
Serial.println(dist_calc);
if(dist_calc<radius){
while(waycont==waypoints){
  buzz();
esc.write(80);
delay(3000);
if(reverse==0){
esc.write(60);
delay(1000);
reverse=1;
}
}
waycont+=1;
}

 flon1 = radians(flon1);
 x2lon = radians(x2lon);

heading = atan2(sin(x2lon-flon1)*cos(x2lat),cos(flat1)*sin(x2lat)-sin(flat1)*cos(x2lat)*cos(x2lon-flon1)),2*3.1415926535;
heading = heading*180/3.1415926535;
int head =heading;
if(head<0){
  heading+=360;
}

Serial.println("heading:");
Serial.println(heading);


int turn=0;
 Wire.beginTransmission(slaveAddress);
  Wire.send("A");             
  Wire.endTransmission();
  delay(10);                 
  Wire.requestFrom(slaveAddress, 2);       
  i = 0;
  while(Wire.available() && i < 2)
  {
    headingData[i] = Wire.receive();
    i++;
  }
  headingValue = headingData[0]*256 + headingData[1];
 int pracheading = headingValue / 10;
 if(pracheading>0){
   headinggps=pracheading;
 }

x4=headinggps-heading;

int x5;


if(x4>=-180){
  if(x4<=0){
    turn=8;    //set turn =8 which means "right"         
  }
}
if(x4<-180){
  turn=5;      //set turn = 5 which means "left"
}
if(x4>=0){
  if(x4<180){
    turn=5;   //set turn = 5 which means "left"
  }
}
if(x4>=180){     //set turn =8 which means "right"
  turn=8;
}

//-------------------------------------------------------------DO NOT TOUCH!!!
float hd = headinggps;
if(hd==heading){
    turn=3;   //then set turn = 3 meaning go "straight"
 
}

if(turn==3){
 
  servo.write(90);  //drive straight
  esc.write(speedesc);
  delay(60);
}
//-------------------------------------------------------------------------------------turn right
if(turn==8){
rightturn();

}
//------------------------------------------------------------------------------------------turn left

if(turn==5){
leftturn();
}

 //-------------------------------------------------------------------------
}

 

void done(){
esc.write(70); 
      done();
}

void rightturn(){
if(headinggps+2>heading){
  if(headinggps-2<heading){
    servo.write(90);
    delay(60);
    return;
  }
}
 x4=headinggps-heading; 
if(x4<-180){
return;
}
if(x4>=0){
  if(x4<180){
  return;
  }
}
servo.write(80);
esc.write(speedesc);
  Wire.beginTransmission(slaveAddress);        //the wire is for the compass module
  Wire.send("A");             
  Wire.endTransmission();
  delay(10);                 
  Wire.requestFrom(slaveAddress, 2);       
  i = 0;
  while(Wire.available() && i < 2)
  {
    headingData[i] = Wire.receive();
    i++;
  }
  headingValue = headingData[0]*256 + headingData[1]; 
headinggps = headingValue / 10;      // this is the heading of the compass
rightturn();
}


//----------------------------------------------left turning
void leftturn(){
  if(headinggps+4>heading){
  if(headinggps-4<heading){
  servo.write(90);
    delay(60);
    return;
  }
}
x4=headinggps-heading; 
if(x4>=-180){
  if(x4<=0){
     return;         
  }
}

if(x4>=180){     
  return;
}
servo.write(110);  // turn wheels left
esc.write(speedesc);

  Wire.beginTransmission(slaveAddress);        //the wire is for the compass module
  Wire.send("A");             
  Wire.endTransmission();
  delay(10);                 
  Wire.requestFrom(slaveAddress, 2);       
  i = 0;
  while(Wire.available() && i < 2)
  {
    headingData[i] = Wire.receive();
    i++;
  }
headingValue = headingData[0]*256 + headingData[1]; 
headinggps = headingValue / 10;      // this is the heading of the compass
leftturn();
}


void buttonread(){
  int butval= analogRead(buttons);
  if(waypoints>0){
  if(butval<100){
    buttonreaddone=5;
        buzz();
      return;
  }
  }
  if(waypoints==0){
    if(butval<100){
      radius+=1;
    buzz();
      return;
    }
  }
      if(butval>600){
     if(waypoints==0){
      flat2=flat;
      flon2=flon;
      waypoints+=1;
         buzz();
      return;
     }
         if(waypoints==1){
      flat3=flat;
      flon3=flon;
      waypoints+=1;
       buzz();
      return;
     }
         if(waypoints==2){
      flat4=flat;
      flon4=flon;
      waypoints+=1;
        buzz();
      return;
     }
         if(waypoints==3){
      flat5=flat;
      flon5=flon;
      waypoints+=1;
        buzz();
      return;
     }
         if(waypoints==4){
      flat6=flat;
      flon6=flon;
      waypoints+=1;
     buzz();
      return;
     }
         if(waypoints==5){
      flat7=flat;
      flon7=flon;
      waypoints+=1;
       buzz();
      return;
     }
          if(waypoints==6){
      flat8=flat;
      flon8=flon;
      waypoints+=1;
         buzz();
      return;
     }
          if(waypoints==7){
      flat9=flat;
      flon9=flon;
      waypoints+=1;
        buzz();
      return;
     }
          if(waypoints==8){
      flat10=flat;
      flon10=flon;
      waypoints+=1;
       buzz();
      return;
     }
          if(waypoints==9){
      flat11=flat;
      flon11=flon;
      waypoints+=1;
     buzz();
      return;
     }
          if(waypoints==10){
      flat12=flat;
      flon12=flon;
      waypoints+=1;
        buzz();
      return;
     }
          if(waypoints==11){
      flat13=flat;
      flon13=flon;
      waypoints+=1;
    buzz();
      return;
     }
       
     }

}
void buzz(){
    while(buzzing<500){
        digitalWrite(buzzer, HIGH);
        delayMicroseconds(250);
        digitalWrite(buzzer, LOW);
        delayMicroseconds(250);
        buzzing++;
      }
      delay(100);
      buzzing=0;
}
David Teles

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.100
  • Helpdesk do sitio
Re: Ler PPM com Arduino
« Responder #10 em: 05 de Novembro de 2012, 01:04 »
Precisas mesmo desses floats todos?
Sabes usar arrays, visto a maneira como estás a usar os floats podias usar um simples array, tornava o código muito mais limpo e legivel.
Avr fanboy

Offline dvdt

  • Mini Robot
  • *
  • Mensagens: 1.228
  • David_@@@_Teles
Re: Ler PPM com Arduino
« Responder #11 em: 05 de Novembro de 2012, 08:19 »
Pois mas foi assim que me explicaram :-[ e nao sei como é que se usa o array
David Teles

StarRider

  • Visitante
Re: Ler PPM com Arduino
« Responder #12 em: 05 de Novembro de 2012, 14:19 »
Boas,

Pois, com todos esses float(s) e cálculos de virgula flutuante e AVR deve estar de rastos ;)

Basicamente necessitas de um timer e um input capture para ler PPM, não te vou poder ajudar em termos
de Arduino, mas posso tentar ajudar a implementar código usando o AVR se estiveres interessado.

Diz-me uma coisa, o sinal PPM que vai ler vem de um receptor RC ?

Abraços,
PA

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.100
  • Helpdesk do sitio
Re: Ler PPM com Arduino
« Responder #13 em: 05 de Novembro de 2012, 19:16 »
O IDE do Arduino tem o compilador avr-gcc assim como o avrdude e mais umas coisas lá, é simplesmente um avr-gcc a correr, e todo o código abaixo das funções bonitas é simplesmente código avr, não percebo porque raio dizem que arduino é uma linguagem de programação -.-
Avr fanboy

Offline dropes

  • Mini Robot
  • *
  • Mensagens: 1.883
Re: Ler PPM com Arduino
« Responder #14 em: 05 de Novembro de 2012, 19:56 »
A instrução "case" também facilita em vez de se colocar "if" em grande parte do código:

if(waycont==1)...if(waycont==12)
if(waypoints==1)...if(waypoints==12)

Código: [Seleccione]
switch (expressions)
{
case constant expressions
}

For example:

switch (i/10)
{
case 0: printf ("Number less than 10"); // A
break;
case 1: printf ("Number less than 20"); // B
break;
case 2: printf ("Number less than 30"); // C
break;
default: printf ("Number greater than or equal to 40"); // D
break; }

Tens razão Senso, assim como AVR nativo não é uma linguagem mas sim assember.
« Última modificação: 05 de Novembro de 2012, 19:59 por dropes »