Arduino sensor motor

Robot, CNC, Pneumatik, Hydraulik, mm
Mike gasoline
Inlägg: 3
Blev medlem: 21 februari 2016, 14:49:53

Arduino sensor motor

Inlägg av Mike gasoline »

Hej
Jag håller på och bygger en autopilot till min båt. Den består av en arduino, rodersensor(0,5-4.5V), dubbla reläer NC/NO , digital kompass och en LCD(16,2) samt en tryckknapp för att spara den kurs jag håller just nu.
Jag är nybörjare när det gäller programmering och har kommit till att jag sparar värdet.
nu vill jag ju att
-om differensen är mer än tex -5 grader.
-starta motor åt vänster tills sensorn gått från 2,5v(512) till ca 2V (410)
-stanna motorn
-delay(50*differens)
-starta motorn till höger till sensorn gått till 2,5v(512)
-Stanna motorn.

tvärt om om det är +5grader.

Min kod så här långt.


#include <DSPC01.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
int delaytime=250;


LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DSPC01 dspc01;

const int buttonPin =2;
const int motorhPin=10;
const int motorvPin=11;
int buttonState = 0;
int sensorPin=A0;

int goal=0;
int sensor=0;
int motorh=LOW;

int motorv=LOW;

int diff=0;
void setup()
{

pinMode(buttonPin, INPUT);
pinMode(motorhPin, OUTPUT);
pinMode(motorvPin, OUTPUT);

Serial.begin(115200);
dspc01.begin(A2,A3);
Serial.println("Compass calibration: Rotate twice horizontally, 360 deg in 3 seconds");
dspc01.calibrate_compass();
delay(6000);
lcd.begin(16,2);



}
void loop()
{


Serial.print(" Compass [deg] ");
//delay(delaytime);
dspc01.request_compass();

delay(delaytime);

int kurs=dspc01.compass();



buttonState = digitalRead(buttonPin);

if (buttonState == HIGH)
{
goal=(kurs);}

else
{
goal==0;

}
Serial.println(kurs);


lcd.clear();

lcd.setCursor(0,0);
lcd.print("K");
lcd.setCursor(0,1);
lcd.print("S");
lcd.setCursor(2,0);

lcd.print(kurs);
lcd.setCursor(2,1);
lcd.print(goal);

diff=(goal-kurs);
if (diff> -5{
motorhPin=HIGH;
}
if (sensor=<400);
motorhPin=LOW;
delay(diff*50);
motorvPin=HIGH;
if (sensor)>512;
motorhPin=LOW;



}



Hur får jag motorn att gå tills sensorn uppnått sitt värde? (jag vet att denna kod inte är rätt)

resten kan jag lista ut tror jag :)

Tacksam om någon har tips.

MVH
Mike gasoline
Användarvisningsbild
Icecap
Inlägg: 26622
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Arduino sensor motor

Inlägg av Icecap »

Välkommen till forumet.

Ska du visa kod bör du använda Code-taggerna, det blir väldigt mycket mer läsbart då.

Normalt använder man en PI-styrning för att styra detta, alltså att felet ackumuleras till det är nog till att köra motorn. Men för att motorn inte ska stå en längre tid med svag ström och bara bli varm brukar man lägga in en dead-band så att styrsignal under t.ex. 10% inte läggs ut för att motorn helt enkelt inte kör under den ström.
Mike gasoline
Inlägg: 3
Blev medlem: 21 februari 2016, 14:49:53

Re: Arduino sensor motor

Inlägg av Mike gasoline »

Ok,
Jag lurade lite på PID med jag kan inte styra DV motorns ström då den är ca 7A. Det gör inget om det blir lite slalom.

Kod: Markera allt

/* Autopilot for yacht
 *  based on Aduino uno, digital compass, dubble relay, angle sensor(0,5V-4,5V)
 */
#include <DSPC01.h>             //bibliotek för kompass
#include <LiquidCrystal_I2C.h>  //bibliotek för LCD
#include <Wire.h>
int delaytime=250;              //väntetid 250ms
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  
DSPC01 dspc01;
const int buttonPin =2;         //d2= pinne för tryckknapp
const int motorhPin=10;         //d10= pinne till relä för att köra motorn åt höger
const int motorvPin=11;         //d11= pinne till relä för att köra motorn åt vänster
int buttonState = 0;            //startvärde för tryckknapp
int sensorPin=A0;               //A0 pinne för rodersensorn
int goal=0;                     //startvärde för målkurs
int sensor=0;                   //startvärde för rodersensor
int motorh=LOW;                 //startvärde för relä höger
int motorv=LOW;                 //startvärde för relä vänster
int diff=0;                     //startvärde för målkurs
void setup()
{
 
 pinMode(buttonPin, INPUT);     //tryckknapps pinne är en input (får in värde 1)
 pinMode(motorhPin, OUTPUT);    //reläpinne för motor åt höger OUTPUT
 pinMode(motorvPin, OUTPUT);    //reläpinne för motor åt vänster OUTPUT
 
 Serial.begin(115200);
 dspc01.begin(A2,A3);           //starta kompass på pinne A2 och A3
 Serial.println("Compass calibration: Rotate twice horizontally, 360 deg in 3 seconds"); //skriver ut "detta" på serial monitor
 dspc01.calibrate_compass();    //kalibrerar kompass
 delay(6000);                   //väntar 6s
lcd.begin(16,2);                //startar LCD, 16 tecken x 2 rader(32 totalt)
 
}
void loop()
{
Serial.print(" Compass [deg] ");                //skriver "Compass deg" i serial monitor
//delay(delaytime);             
dspc01.request_compass();                       //anropar kompassvärde från digitalakompassen
delay(delaytime);                               // väntar delaytime som specats ovan
int kurs=dspc01.compass();                      //kurs lika med kompassvärdet
 
 buttonState = digitalRead(buttonPin);          //läser av tyckknappsvärdet
  if (buttonState == HIGH)                      //om knapp intryckt spara kurs som målvärde annars målvärde 0
{
 goal=(kurs);}
else
{
 goal==0;
}
Serial.println(kurs);                           //skriver ut kurs i serial monitor
 lcd.clear();                                   //tömmer LCD på tecken
 
   lcd.setCursor(0,0);                          //ställer markör på rad 1 tecken 1
    lcd.print("K");                             //skriver "K" först på rad ett
    lcd.setCursor(0,1);                         //ställer markör på rad 2 tecken 1
    lcd.print("S");                             //Skriver "S" först på rad två
    lcd.setCursor(2,0);                         //ställer markör på rad ett och tecken 3
    lcd.print(kurs);                            //skriver ut kusrvärdet
    lcd.setCursor(2,1);                         //ställermarkör på rad 2 tecken 3
    lcd.print(goal);                            //skriver ut Goalvärdet(sparad kurs)
  sensor=analogRead(sensorPin);                 //läser av rodersensor
diff=(goal-kurs);                               //diff är lika med målkurs-aktuell kurs

if (diff>180){                                  //om diff är större än 180 grader, då är diff 360-diff
  diff=(360-diff);
}
  else if (diff<-180){                          //annars om diff är mindre än -180 grader, då är diff -360-diff
  diff=(-360-diff);
  }
else {
  diff;                                         //annars är diff diff
  }

 if  (diff< -5)  {                              //om diff är mindre än -5 starta motor åt höger medans sensorn är större än 400
    do digitalWrite(motorh, HIGH);
    while (analogRead(sensorPin)>400);
    digitalWrite(motorh, LOW);                  //stanna motorhöger
    delay(50);                                  //vänta 50ms
    do digitalWrite(motorv, HIGH);              //starta motorvänster medans sensorn är mindre än 500
    while (analogRead(sensorPin)<500);
    digitalWrite(motorv, LOW);                  //stanna motorvänster
  }
  else if (diff> 5){                            //om diff större än +5 starta motor åt vänster medans sensor är mindre än 600
     do digitalWrite(motorv, HIGH);
    while (analogRead(sensorPin)<600);
    digitalWrite(motorv, LOW);                  //stanna motorvänster
    delay(50);
    do digitalWrite(motorh, HIGH);              //starta motorhöger medans sensor är större än 500
    while (analogRead(sensorPin)>500);          
    digitalWrite(motorh, LOW);                  //stanna motorhöger
  }
     {
  }
  
 }
 
Användarvisningsbild
Icecap
Inlägg: 26622
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Arduino sensor motor

Inlägg av Icecap »

Jo då, du kan visst styra motorns ström! Man kallar det PWM, alltså tända och släcka snabbt. Medeleffekten kan så styra motorns hastighet - om man vill det.

Men det finns andra sätt:
Om motorn ska "flyttas lite" kan man ha en reglering som ger motorn pulser av ström. Pulsernas längd uppfyller två regler:
1: Inte för kort, det är nämligen inte lönt, den rör inte nog på sig till att det betyder något.
2: Inte för lång, då blir det nämligen överreglering.

Så om riktningen är liiiite fel tar det ett tag innan den korta korrigeringspulsen till motorn utlösas.
Är riktningen mer fel går det snabbare att "spara ihop" till en puls.
Är det helt galet fel blir det längre pulser relativt tät på varandra.

Och jo, det gör faktisk något om det blir lite slalom: det brukar mer effekt till rodermotorn. Kan vara försumbar men ändå, det är lika bra att göra en bra lösning när man väl är igång.
granberget
Inlägg: 7
Blev medlem: 7 mars 2016, 22:21:32

Re: Arduino sensor motor

Inlägg av granberget »

Gjorde om din kod lite, samt ett förslag på hur du kan köra motorerna i kortare pulser.
Är skillnaden på önskad och faktisk kurs liten så kör motorerna kortare pulser, är skillnaden stor kör de längre.
Du får själv lägga in rodersensorn så rodret tar sig mot mitten när differansen är liten, men här har du ett förslag iallafall! :)

Kod: Markera allt

#include <DSPC01.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
int delaytime=250;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
DSPC01 dspc01;

const int buttonPin = 2;
const int motorH = 10;
const int motorV = 11;
int sensorPin = A0;

int goal = -1;
int sensor = 0;
int diff = 0;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(motorhPin, OUTPUT);
  pinMode(motorvPin, OUTPUT);

  Serial.begin(115200);
  dspc01.begin(A2,A3);
  .println("Compass calibration: Rotate twice horizontally, 360 deg in 3 seconds");
  dspc01.calibrate_compass();
  delay(6000);
  lcd.begin(16,2);
}

void loop() {
  //-----------------------------------------
  // Hämta värde från kompass och spara i kurs
  //-----------------------------------------
  dspc01.request_compass();
  int kurs = dspc01.compass();

  Serial.print(" Compass [deg] ");
  Serial.println(kurs);

  delay(delaytime);

  //-----------------------------------------
  // Om knapp trycks in: spara kurs
  //-----------------------------------------
  if (digitalRead(buttonPin) == HIGH){
    goal = (kurs);
  }

  //-----------------------------------------
  // Skriv önskad och faktisk kurs till LCD
  //-----------------------------------------
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("K ");
  lcd.print(kurs);
  lcd.setCursor(0,1);
  lcd.print("S ");
  lcd.print(goal);
 
  //-----------------------------------------
  // Om ingen kurs har valts hoppar programmet över detta
  //-----------------------------------------
  if ( goal != -1){
    diff = (goal-kurs);

    //-----------------------------------------
    // Om differansen är liten, kör motor korta pulser
    //-----------------------------------------
    if (diff > -5 || diff < 5)
    {
        if (diff < 0){ // Om diff är negativ
          motorH = HIGH;
        }
        else {        // Om diff är positiv
          motorV = HIGH;  
        }
        Delay(200);
        motorH = LOW;
        motorV = LOW;
        Delay(200);
    }

    //-----------------------------------------
    // Om differansen är stor, kör motor längre
    //-----------------------------------------
    else {
      if (diff < 0){  // Om diff är negativ
          motorH = HIGH;
        }
        else {        // Om diff är positiv
          motorV = HIGH;  
        }
        Delay(600);
        motorH = LOW;
        motorV = LOW;
        Delay(200);
    }    
  }
}
Mike gasoline
Inlägg: 3
Blev medlem: 21 februari 2016, 14:49:53

Re: Arduino sensor motor

Inlägg av Mike gasoline »

Tack icecap!
Tyvärr kommer reläerna brinna upp om de slå till och från hela tiden. Funderar på en H-brygga. Då kan det funka. Ska lura lite på det.
Med vänlig hälsning,
Micke
Användarvisningsbild
Icecap
Inlägg: 26622
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Arduino sensor motor

Inlägg av Icecap »

Mike gasoline: en enkel lösning är att ha ett relä som polvändare. Sedan behöver du en enda MOSFET som du driver med PWM, då har du allt i ett paket. Men ja, en H-brygga är bättre.
Skriv svar