Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  16 1798
Eg har to arduinoar på kontrollen til roboten min. Den eine er kopla til ein g-sensor. Den andre er kopla til ein nRF905-sendar. Målet mitt er at arduinoen som er kopla til g-sensoren skal kunne sende eit array med kommandoar til den andre arduinoen. Denne sender dette vidare til nRF905.

Arrayet skal sjå slik ut: [mode byte (1 eller 0), byte for kva motor som skal drivast (1-4), speed control (0-255)]

Eg får sendt arrayet ut frå den første arduinoen, men når eg skal motta og sende vidare med den andre, brukar den altfor lang tid på å motta data. Roboten blir med andre ord ståande i ro.

Kode arduino 1:

Kode

int g_sensor_x;
  int g_sensor_y;
  byte data[3];
  g_sensor(g_sensor_x, g_sensor_y); // Hentar data frå g-sensor. x og y varierer mellom -255 og 255 etter kva g-krefter sensoren er utsatt for.

  
  byte data[3];
  
   while(g_sensor_x > 0 && g_sensor_x > -g_sensor_y && g_sensor_x > g_sensor_y)
    {
      data[0]=0; 
      data[1]=1;
      data[2]=g_sensor_x;   
      Serial.write(data, 3); 
  
      g_sensor(g_sensor_x, g_sensor_y); 
    }
    
    
    while(g_sensor_x < 0 && -g_sensor_x > -g_sensor_y && -g_sensor_x > g_sensor_y)
    {
      data[0]=0; 
      data[1]=2;
      data[2]=-g_sensor_x;  
      Serial.write(data, 3);

      g_sensor(g_sensor_x, g_sensor_y);
     }
     
     
    while(g_sensor_y >0 && g_sensor_y > -g_sensor_x && g_sensor_y > g_sensor_x)
    { 
      data[0]=0; 
      data[1]=3;
      data[2]=g_sensor_y;
      Serial.write(data, 3);
      g_sensor(g_sensor_x, g_sensor_y);
     }
    while (g_sensor_y < 0 && -g_sensor_y > -g_sensor_x && -g_sensor_y > g_sensor_x)
    {
      data[0]=0; 
      data[1]=4;
      data[2]=-g_sensor_y;  
      Serial.write(data, 3);
 
      g_sensor(g_sensor_x, g_sensor_y);
    }
Arduino 2:

Kode

  
byte data[3];
char seriell_data[3];

while(Serial.available())
  { 
    Serial.readBytes(seriell_data, 3);
    data[0] = seriell_data[0];
    data[1] = seriell_data[1];
    data[2] = seriell_data[2];
    
    nRF905_setTXAddress(TXADDR);
    nRF905_setData(data, sizeof(data));
    while(!nRF905_send());
  }
Som de kan sjå har eg også problemar med at Serial.readBytes gir ut data i form av char. Medan nRF905 berre kan handtere byte.

Baud rate er satt til 115200kbps for begge arduinoane

Er det nokon som har peiling på overføring av arrays her?
Sikkerhetsklarert
Jeg aner ikke hvordan du skal gjøre det seriellt, men
kan du sende verdiene analogt, eller med pwm i stedet?
Sitat av Pjukern Vis innlegg
Jeg aner ikke hvordan du skal gjøre det seriellt, men
kan du sende verdiene analogt, eller med pwm i stedet?
Vis hele sitatet...
Grunnen til at gjer det seriellt er fordi eg ikkje har nok pins igjen på den andre arduinoen. Hadde eg hatt det, så hadde eg ikkje trengt den ekstra arduinoen
Så ikke så grundig igjennom koden (det er sent :P ), men jeg ser at du har en array som heter data[], men du spesifiserer ikke hvilken kolonne som skal sendes, du skriver "serial.write (data, 3)", vil ikke dette føre til kompilasjonserror?

Fungerer det hvis du gjør noe så simpelt som:

Serial.write(0xAA);

og:

if (Serial.available > 0) {
int x=Serial.read();
}

Hvis dette fungerer så kan du bare jobbe deg framover
Sitat av Plecto Vis innlegg
Så ikke så grundig igjennom koden (det er sent :P ), men jeg ser at du har en array som heter data[], men du spesifiserer ikke hvilken kolonne som skal sendes, du skriver "serial.write (data, 3)", vil ikke dette føre til kompilasjonserror?

Fungerer det hvis du gjør noe så simpelt som:

Serial.write(0xAA);

og:

if (Serial.available > 0) {
int x=Serial.read();
}

Hvis dette fungerer så kan du bare jobbe deg framover
Vis hele sitatet...
Eg får sendt data med det eg har no og, det går berre for sakte å motta den. Frå arduino 1 sender ei endring i data, tar det lang til før arduino 2 leser den. Det kan sjå ut som arduino 2 har problemar med å tygge unna dataen frå arduino 1 før den sender ny.

Serial.write skal kunne skrive ut arrays:
Serial.write(buf, len)
Arduino 1:
byte data[3];
både på linje 3 og 7.

Char og bytes er samme lengde, dessuten finnes ikke datatyper over seriell overføring, kun en en 8 bit verdi for hvert telegram. Hva skjer hvis du skriver
byte seriell_data[3]; i stedet for
char seriell_data[3]; på linje 3 (arduino 2)?
Fra arduino.cc
Parameters
buffer: the buffer to store the bytes in (char[] or byte[])
Vis hele sitatet...
Det som nok er problemet ditt er at bufferet i ReadBytes, er fullt. Når du kaller den funksjonen kan du hente tilbake hvor mange plasser som er opptatt, slik
AntallBytesIBuffer = Serial.readBytes(seriell_data, 3);

Ser ut som du kan cleare bufferet med Serial.Flush(); men det har jeg ikke testet. Du kan uansett prøve å legge det til rett under der du leser ut dataen.
Fekk overføringa til å fungere ved å bruke flush på arduino 1. Dessverre var ikkje hastigheita høg nok til at eg kunne bruke det direkte til å styre roboten. Fekk omorganisert brytarane på arduino 2 slik at eg ikkje hadde bruk for den ekstra arduinoen.

"buffer: the buffer to store the bytes in (char[] or byte[])" Merkelig nok støtter ikkje funksjonen eit byte-array.
Hvorfor brukte du flush på arduino 1? Den bruker jo ikke noe buffer, den bare sender ut et array på seriellporten. Prøv å gjøre som jeg sa, hva skjer da?

Du sier at hastigheten ikke er høy nok men det betyr bare at du har gjort noe galt. Vi snakker 3 stk 8-bits verdier på 9600kbps, vi prøver ikke å laste ned en film i HD heller.
Du sender ikke data for ofte til serial out, da? Har du prøvd å legge inn et delay i koden på sende-enheten?
Gerbizzle, du har nok løsningen! Programmet på mottakerenden er jo låst i en evig løkke fordi telegrammene sendes i en evig løkke.
Sitat av Gerbizzle Vis innlegg
Du sender ikke data for ofte til serial out, da? Har du prøvd å legge inn et delay i koden på sende-enheten?
Vis hele sitatet...
Har faktisk prøvd med delay på senderen. Det fungerte til ein viss grad. Roboten rykka seg framover. Roboten brukar verdiane direkte til styring etc. Det skal mao. lite til før den ikkje får bevegd seg Det små delayet den får når dataen overførast arduino-arduino-radiosendar blir for stort.

Fekk fiksa det slik at eg ikkje har bruk for begge arduinoane ved å bruke pin 0 og 1 til sensoren. Skal sjå på overføring av arrays etter kvart, men akkurat no må eg berre bli ferdig.
Du kan jo selv velge båndbredden på responsen til roboten ved å variere delayen. Dessuten, du skal ikke ha en faktisk delay, for det halter hele programmet. Du skal rett og slett ha en pause fra å motta data så den får tygd litt utenom seriellmottak-loopen.
Og slik jeg ser det, så trenger du ikkje 3 byte for å sende mode ( 1-bit ), motor ( 2-bit ) og speed ( 8-bit ), du hadde klart deg med under 1.5 byte, men siden det krever hele byte så for du nøye deg med 2 byte. Jeg har satt opp et forslag her til deg.



Den zeropadding der kan du bruke til det du ønsker, sette kontroll flag eller sende andre verdier, du har 5 byte til overs.
Sitat av 0xFF Vis innlegg
..du har 5 byte til overs.
Vis hele sitatet...
5 bit så klart. Beklager å påpeke det åpenbare, men i tilfelle du ble misforstått av andre :P

Det er ingen dum idé du kommer med her, men som jeg har sagt over så tviler jeg på at det er datatrafikken som sinker dette systemet, det er hvordan det er programmert. Bufferet kan bli fullt og ved kontinuerlig sending/mottak vil programmet bli liggende inni disse løkkene. Så om det er 2 eller 3 bytes som sendes... Han må jo bruke en et par instruksjoner for å maske ut de bitsene han trenger og, ikke at det tar så mange prosessorsykluser men det blir mer avansert for en nybegynner.
Sitat av wanna-b Vis innlegg
5 bit så klart. Beklager å påpeke det åpenbare, men i tilfelle du ble misforstått av andre :P
Vis hele sitatet...
Selvsagt, my bad.

Sitat av wanna-b Vis innlegg
Det er ingen dum idé du kommer med her, men som jeg har sagt over så tviler jeg på at det er datatrafikken som sinker dette systemet, det er hvordan det er programmert. Bufferet kan bli fullt og ved kontinuerlig sending/mottak vil programmet bli liggende inni disse løkkene. Så om det er 2 eller 3 bytes som sendes... Han må jo bruke en et par instruksjoner for å maske ut de bitsene han trenger og, ikke at det tar så mange prosessorsykluser men det blir mer avansert for en nybegynner.
Vis hele sitatet...
Jeg påstår ikkje at det kommer til å løse problemet hans, annet enn at det optimaliserer dataoverføringen litt. Men etter å sett litt nærmere på koden så skjønner jeg hva du mener, her er det mye som kan optimaliseres. Blant annet så ville jeg ha laget egne funksjoner for å pakke dataen samt sende den og en funksjon for å motta å unpakke dataen.

Jeg har sittet å studert litt de while loopene, men klarer ikkje å forstå hvorfor dem er satt opp slik. Er det meningen at når siste loopen terminerer så skal hele arduino'en restarte og starte på nytt?

Har også satt opp en sannhetstabel over while loopene, helt til høre er verdiene

Kode

GSX = g_sensor_x
GSY = g_sensor_y
lengere til høyre er det 4 grupper der betingelsen står øverst,

Kode

X = g_sensor_x
Y = g_sensor_y
så da blir

Kode

-X > Y
det samme som

Kode

-g_sensor_x > g_sensor_y
Hver gruppe har en kolonne med tittelen "AND", denne summerer de 3 kolonnene til venstre for den med bitwise AND. I tillegg står det en gruppe helt til høyre med tittelen "OR" som sjekker om noen av while loopene er TRUE.



Så hvis man ser på OR kolonnen, vil man se at i ca 50% av tilfellene så vil arduinoen boote, hente g_sensor_x og g_sensor_y verdiene, rushe igjennom while loopene uten å kjøre det som står innenfor blokka og terminere programmet, for så å reboote?

Hvis dette er tilfelle så er det ikkje rart at overføringen av data mellom de to arduino går sakte.

RETTELSE: Jeg hadde glemt en kolonne i betingelsen til "OR" kolonnen, så jeg har oppdatert det. Og prosent andelen for antall ganger den bare kjører rett igjennom uten å utføre noe, har gått ned fra 50% til ~35%.

Sitat av 0xFF Vis innlegg
Jeg har sittet å studert litt de while loopene, men klarer ikkje å forstå hvorfor dem er satt opp slik. Er det meningen at når siste loopen terminerer så skal hele arduino'en restarte og starte på nytt?
Vis hele sitatet...
Nei, jeg må bare tolke det som et utsnipp av koden hans. Iom. at det er arduino 2 som styrer selve roboten må det være noe annet der. Denne loopen ligger sikkert inni en main loop, og entres når det er seriell data tilgjengelig. I hans tilfelle betyr det: alltid.
Eg får vel legge ut koden då

Slik det er koda no, brukar eg ikkje den ekstra arduinoen.

TX

Kode

// Laste inn bibliotek
#include <nRF905.h>
#include <nRF905_config.h>
#include <nRF905_defs.h>
#include <nRF905_types.h>
#include <SPI.h>

//Lage RX/TX-addresser
#define RXADDR 0x44332211
#define TXADDR 0x99887766

//Deklarer I/O 
const int fram_knapp     = A0;
const int bak_knapp      = A1;
const int venstre_knapp  = A2;
const int hogre_knapp    = A3;
const int mode1_bryter   = 0;
const int mode2_bryter   = 1;
const int fart_pot       = A5;
const int acc_x          = 5;
const int acc_y          = 6;

void setup()
{
  //Start nRF905
  nRF905_init();

  //Sett RX/TX-addresser
  nRF905_setRXAddress(RXADDR);
  nRF905_setTXAddress(TXADDR);

  //Sett pinModes
  pinMode(mode1_bryter, INPUT);
  pinMode(mode2_bryter, INPUT);
  pinMode(acc_x, INPUT);
  pinMode(acc_y, INPUT);
}

void loop()
{
  //Les data frå knappane/potmeter
  int fram     = digitalRead(fram_knapp);
  int bak      = digitalRead(bak_knapp);
  int venstre  = digitalRead(venstre_knapp);
  int hogre    = digitalRead(hogre_knapp);
  int mode1    = digitalRead(mode1_bryter);
  int mode2    = digitalRead(mode2_bryter);
  int fart     = analogRead(fart_pot);
  fart = fart/4;

  //lag array for data
  byte data[3];

  //les data frå akselerometer
  int g_sensor_x;
  int g_sensor_y;
  g_sensor(g_sensor_x, g_sensor_y);


  if(mode1 == 0 && mode2 == 0)
  { 
    g_sensor_control(g_sensor_x, g_sensor_y);
  }

  if (mode1 == 1 && mode2 == 0)
  {
    //Sett datapakkar igjen
    data[0] = 1; //data på plass 0 styrer mode til robot
    data[1] = 0; //data plass 1 er ikkje relevant
    data[2] = fart; //data[2] styrer fart

    //Send datapakka til nRF905
    nRF905_setData(data, sizeof(data));
    //Send data 
    while(!nRF905_send());

  }

  if (mode2 == 1 && mode1 == 0 )
  {
    //Sett datapakkar
    data[1] = 0;
    data[0] = 0; //data på plass 0 styrer mode til robot
    data[2] = fart;

    if(fram == 1)
    {
      data[1] = 1;
    }

    else if(bak == 1)
    {
      data[1] = 2;
    }
    else if (venstre == 1)
    {
      data[1] = 3;
    }
    else if(hogre == 1)
    {
      data[1] = 4;
    }
    
    nRF905_setData(data, sizeof(data));
    while(!nRF905_send());
  }


}

void g_sensor(int& resultat_x, int& resultat_y)
{
  long puls_x = pulseIn(acc_x, HIGH);
  long puls_y = pulseIn(acc_y, HIGH);

  float duty_x = puls_x/=100;
  float duty_y = puls_y/=100;
  
  float konstant = -20.08;
  
  resultat_x = (konstant*duty_x)+996.55;
  resultat_y = (konstant*duty_y)+996.55;
}

void g_sensor_control(int g_sensor_x, int g_sensor_y)
{
  //Lag array
  byte data[3];

  if(g_sensor_x > 0 && g_sensor_x > -g_sensor_y && g_sensor_x > g_sensor_y)
  {
    data[0] = 0; 
    data[1] = 1;
    data[2] = g_sensor_x;   
  }

  if(g_sensor_x < 0 && -g_sensor_x > -g_sensor_y && -g_sensor_x > g_sensor_y)
  {
    data[0] = 0; 
    data[1] = 2;
    data[2] = -g_sensor_x;  
  }

  if(g_sensor_y >0 && g_sensor_y > -g_sensor_x && g_sensor_y > g_sensor_x)
  { 
    data[0] = 0; 
    data[1] = 3;
    data[2] = g_sensor_y;
  }
  if(g_sensor_y < 0 && -g_sensor_y > -g_sensor_x && -g_sensor_y > g_sensor_x)
  {
    data[0] = 0; 
    data[1] = 4;
    data[2] = -g_sensor_y;  
  }
  //send data
  nRF905_setData(data, sizeof(data));
  while(!nRF905_send());
}
Robot

Kode

//Legg til bibliotek
#include <SoftPWM.h> 
#include <SoftPWM_timer.h>
#include <Servo.h>
#include <nRF905.h>
#include <nRF905_config.h>
#include <nRF905_defs.h>
#include <nRF905_types.h>
#include <SPI.h>

//Lag ein servo kalla myservo
Servo myservo;

//Deklarer konstantar for I/O-pins
const int v_b = A0;
const int h_f = A1;
const int v_f = A2;
const int h_b = A3;
const int trig = A4;
const int echo = A5;

//Lag RX/TX-addresser
#define RXADDR 0x99887766
#define TXADDR 0x44332211

void setup()
{
  //Sett pinmodes for motor
  pinMode(v_b, OUTPUT);
  pinMode(h_f, OUTPUT);
  pinMode(v_f, OUTPUT);
  pinMode(h_b, OUTPUT);
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);

  //Velg pin for servo
  myservo.attach(6);

  //Sett servo i rett posisjon
  myservo.write(100);

  //Starte nRF905
  nRF905_init();

  //Sette RX-addresse
  nRF905_setRXAddress(RXADDR);

  //Sette i receive-modus
  nRF905_receive();

  //Start softPWM
  SoftPWMBegin();

  //Sett softPWM pins låge
  SoftPWMSet(v_b, 0);
  SoftPWMSet(h_f, 0);
  SoftPWMSet(v_f, 0);
  SoftPWMSet(v_b, 0);

  //Sett fade time(Kor lang tid i ms det tar å gå frå 0-255 og 255-0)
  SoftPWMSetFadeTime(ALL, 100, 500);
  Serial.begin(9600);

}

void loop()
{

  //lage variabel for modus
  //int modus;
  //Motta modebyte frå sendar

  //lage buffer for mottak
  byte data[3];

  //Mottda data (medan mottaker ikkje får data, køyrer den løkka)
  while(!nRF905_getData(data, sizeof(data)));
  // Sett mode lik data[0];
  //modus = data[0];
  
  // Viss modus == 1, sett i automat
  if (data[0] == 1)
  {
    automat_modus();
  }
  
  //Viss modus == 0, sett i RC-Modus
  if (data[0] == 0)
  {
    rc_modus();
  }
}



void automat_modus()
{
  //Lag variabel for lagring av data frå ping))) sensor
  long cm;
  //Lag variablar for måling av ping)))-sensor høgre/venstre
  long cm_venstre, cm_hogre;

  //lag buffer for lagring av data frå sendar
  byte data[3];

  //Hent data frå sendar
  while(!nRF905_getData(data, sizeof(data)));

  while(data[0]==1)
  {
  //Hent data frå nRF905
  while(!nRF905_getData(data, sizeof(data)));
  
  //Mål avstand
  cm = ping();
    
    while(cm > 20)
    { 
      r_fram(data[2]);
      cm = ping();
      while(!nRF905_getData(data, sizeof(data)));
    }

    while (cm < 20)
    {
      r_bak(data[2]); //Bremse
      delay(500);
      r_stop();       //Stopp
      delay(500);

      myservo.write(180); // sjå til venstre
      delay(1000);
      cm_venstre = ping(); // Mål avstand

      myservo.write(0); // Sjå til høgre
      delay(1000);
      cm_hogre = ping(); // Mål avstand

      r_bak(data[2]);  //Køyr litt tilbake
      delay(500);
      r_stop();        //Stopp
      delay(500);
      myservo.write(90); //Sentrer
      delay(1000);
      
      //Bestem retning
      if (cm_venstre > cm_hogre) 
      {
        r_venstre(data[2]); 
        delay(500);
        r_stop();
        delay(500);
      }
      else
      {
        r_hogre(data[2]);
        delay(500);
        r_stop();
        delay(500);
      }
      while(!nRF905_getData(data, sizeof(data)));
      cm = ping();
    }
  }
}

void rc_modus()
{
  //array for lagring av data
  byte data[3];
  //hent data
  while(!nRF905_getData(data, sizeof(data)));

  //Køyr løkka medan senderen står i RC-modus
  while(data[0]==0)
  {
    while(!nRF905_getData(data, sizeof(data)));
    //Serial.println(data[1]);
    //Køyrekommandoar for RC_modus data[1]= retning, data[2]=fart
    Serial.println(data[2]);
    switch(data[1])
    {
    case 1:
      r_fram(data[2]);
      break;

    case 2:
      r_bak(data[2]);
      break;

    case 3:
      r_venstre(data[2]);
      break;

    case 4:
      r_hogre(data[2]);
      break;
    
    case 0:
      r_stop();
      break;  

    default:
      r_stop();
      break;
    }

  }
}

long ping() // Funksjonen måler avstanden til ein gjenstand vha ultralyd
{
  long cm;
  long puls;
  
  digitalWrite(trig, LOW);
  delayMicroseconds(5);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  
  puls = pulseIn(echo, HIGH);
  
  cm = (puls*34/1000)/2; //(Periodetid*lydhastigheit/(1000000(konvertering til sekund)/100(for å få cm)/2(lyden skal fram og tilbake)
  Serial.println(cm);
  return cm;
}


//Køyrefunksjonar for motorane (h,v,f,b)
void r_stop() // Robot stopp
{
  SoftPWMSet(v_b, 0);
  SoftPWMSet(v_f, 0);
  SoftPWMSet(h_b, 0);
  SoftPWMSet(h_f, 0);
}

void r_fram(int fart) // Robot fram
{
  SoftPWMSet(v_b, 0);
  SoftPWMSet(h_f, fart);
  SoftPWMSet(h_b, 0);
  SoftPWMSet(v_f, fart);
}

void r_bak(int fart ) // Robot bak
{
  SoftPWMSet(v_b, fart);
  SoftPWMSet(v_f, 0);
  SoftPWMSet(h_b, fart);
  SoftPWMSet(h_f, 0);
}

void r_hogre(int fart) // robot høgre
{
  fart = fart*1.2;
  if(fart >= 255){fart=255;}
  Serial.println(fart);
  SoftPWMSet(v_b, 0);
  SoftPWMSet(v_f, fart);
  SoftPWMSet(h_b, fart);
  SoftPWMSet(h_f, 0);
}

void r_venstre(int fart) // robot venstre
{
  fart = fart*1.2;
  if(fart >= 255){fart=255;}
  Serial.println(fart);
  SoftPWMSet(v_b, fart);
  SoftPWMSet(v_f, 0);
  SoftPWMSet(h_b, 0);
  SoftPWMSet(h_f, fart);
}
Det er sikkert mykje som kan forbetrast her. Eg har planar om å legge RC modus og auto inn i eigne funksjonar på TX-delen for å få ein litt "finare" loop.

Det største problemet no er at motorane drar for mykje straum. Noko som fører til problemar med ping-sensoren.