• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Modyfikacja kodu dla pojazdu
#1
Kod:
//There id more information aboat this code in Page 26 of "Instruction manual-English.pdf"

// This code is for the bluetooth and infrared controlled ultrasonic arduino car.
// By default, the buttons 2, 4, 6 en 8 of the remote will move the car in infrared mode.
// Ultrasonic mode is enabled by the play/pause button.
// Track following is enabled by the EQ button.
// Button 5 will stop whatever the car is doing and enable button 2, 4, 6 en 8 again.
// Bluetooth is always enabled and available while in infrared mode. The password is 1234.
//
// Android car control app can be found here:
// https://play.google.com/store/apps/details?id=braulio.calle.bluetoothRCcontroller&hl=en

//Code based on code found at icstation.com and banggood.com (same sources)
//Modifications
//   Continuous movement possible with both bluetooth and ir control
//   Customization of servo angles
//   Moved up all constants that might need customization
//   Added simular code in functions, reducing code lines and complexity
//   Broken down long functions in smaller ones to reduce complexity
//   Removed unused signals
//   Reduced global variables by creating local variables

//********Include libraries*********************************************
#include <IRremote.h>
#include <Servo.h>
#include <avr/interrupt.h>

// Defining IR_GLOBAL here allows us to declare the instantiation of global variables
#define IR_GLOBAL
#  include "IRremote.h"
# include "IRremoteInt.h"
#undef IR_GLOBAL

//+=============================================================================
// The match functions were (apparently) originally MACROs to improve code speed
//   (although this would have bloated the code) hence the names being CAPS
// A later release implemented debug output and so they needed to be converted
//   to functions.
// I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some
//   reason, no matter what I did I could not get them to function as macros again.
// I have found a *lot* of bugs in the Arduino compiler over the last few weeks,
//   and I am currently assuming that one of these bugs is my problem.
// I may revisit this code at a later date and look at the assembler produced
//   in a hope of finding out what is going on, but for now they will remain as
//   functions even in non-DEBUG mode
//



//+========================================================
// Due to sensor lag, when received, Marks tend to be 100us too long
//
//+========================================================
// Due to sensor lag, when received, Spaces tend to be 100us too short
//
//+=============================================================================
// Interrupt Service Routine - Fires every 50uS
// TIMER2 interrupt code to collect raw data.
// Widths of alternating SPACE, MARK are recorded in rawbuf.
// Recorded in ticks of 50uS [microseconds, 0.000050 seconds]
// 'rawlen' counts the number of entries recorded so far.
// First entry is the SPACE between transmissions.
// As soon as a the first [SPACE] entry gets long:
//   Ready is set; State switches to IDLE; Timing of SPACE continues.
// As soon as first MARK arrives:
//   Gap width is recorded; Ready is cleared; New logging starts
//
ISR (TIMER_INTR_NAME)
{
 TIMER_RESET;

 // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
 // digitalRead() is very slow. Optimisation is possible, but makes the code unportable
 uint8_t  irdata = (uint8_t)digitalRead(irparams.recvpin);

 irparams.timer++;  // One more 50uS tick
 if (irparams.rawlen >= RAWBUF)  irparams.rcvstate = STATE_OVERFLOW ;  // Buffer overflow

 switch(irparams.rcvstate) {
   //......................................................................
   case STATE_IDLE: // In the middle of a gap
     if (irdata == MARK) {
       if (irparams.timer < GAP_TICKS)  {  // Not big enough to be a gap.
         irparams.timer = 0;

       } else {
         // Gap just ended; Record duration; Start recording transmission
         irparams.overflow                  = false;
         irparams.rawlen                    = 0;
         irparams.rawbuf[irparams.rawlen++] = irparams.timer;
         irparams.timer                     = 0;
         irparams.rcvstate                  = STATE_MARK;
       }
     }
     break;
   //......................................................................
   case STATE_MARK:  // Timing Mark
     if (irdata == SPACE) {   // Mark ended; Record time
       irparams.rawbuf[irparams.rawlen++] = irparams.timer;
       irparams.timer                     = 0;
       irparams.rcvstate                  = STATE_SPACE;
     }
     break;
   //......................................................................
   case STATE_SPACE:  // Timing Space
     if (irdata == MARK) {  // Space just ended; Record time
       irparams.rawbuf[irparams.rawlen++] = irparams.timer;
       irparams.timer                     = 0;
       irparams.rcvstate                  = STATE_MARK;

     } else if (irparams.timer > GAP_TICKS) {  // Space
         // A long Space, indicates gap between codes
         // Flag the current code as ready for processing
         // Switch to STOP
         // Don't reset timer; keep counting Space width
         irparams.rcvstate = STATE_STOP;
     }
     break;
   //......................................................................
   case STATE_STOP:  // Waiting; Measuring Gap
     if (irdata == MARK)  irparams.timer = 0 ;  // Reset gap timer
     break;
   //......................................................................
   case STATE_OVERFLOW:  // Flag up a read overflow; Stop the State Machine
     irparams.overflow = true;
     irparams.rcvstate = STATE_STOP;
     break;
 }

 // If requested, flash LED while receiving IR data
 if (irparams.blinkflag) {
   if (irdata == MARK)
     if (irparams.blinkpin) digitalWrite(irparams.blinkpin, HIGH); // Turn user defined pin LED on
       else BLINKLED_ON() ;   // if no user defined LED pin, turn default LED pin for the hardware on
   else if (irparams.blinkpin) digitalWrite(irparams.blinkpin, LOW); // Turn user defined pin LED on
       else BLINKLED_OFF() ;   // if no user defined LED pin, turn default LED pin for the hardware on
 }
}

//Pin assignments and global variables per function. Customize if needed
//*******Pin assignments Motor board and IR receiver********************
const int MotorRight1 = 7;
const int MotorRight2 = 8;
const int MotorLeft1 = 9;
const int MotorLeft2 = 10;
const int MotorRightPWM = 6;
const int MotorLeftPWM = 11;
const int irReceiverPin = A0;
const int servoPin = 2; //orange wire
int iSpeed = 255; //speed, range 0 to 255
const int LedPin=13;
//******Infrared key bindings********************************************
const long IRfront = 0x00FF18E7;      //go straight: button 2
const long IRback = 0x00FF4AB5;       //go back    : button 8
const long IRturnright = 0x00FF10EF;  //turn right : button 6
const long IRturnleft = 0x00FF5AA5;   //turn left  : button 4
const long IRstop = 0x00FF38C7;       //stop       : button 5
const long IRcny70 = 0x00FFE01F;      //CNY70 automatic mode: button EQ
const long IRAutorun = 0x00FF22DD;    //Ultrasonic mode : button play/pause
//******Track following pin assignments and signals**********************
const int SensorLeft = 5;      //
const int SensorMiddle = 4 ;   //
const int SensorRight = 3;     //
IRrecv irrecv(irReceiverPin);  // IRrecv signal
decode_results infrared;       // decode result
//*******Ultrasonic pin assignments and signals**************************
const int echoPin = 12; // ultrasonic receive=echo pin
const int triggerPin = 13; // ultrasonic send=trigger pin
Servo myservo; // define myservo
const int degreesForward = 130; //nr degrees to look forward
const int degreesLeft = 60; //nr degrees to look left
const int degreesRight = 180; //nr degrees to look right
const int delay_time = 250; // servo motor delay
const int Fgo = 8; // go straight
const int Rgo = 6; // turn right
const int Lgo = 4; // turn left
const int Bgo = 2; // go back
//*****Bluetooth signals**************************************************
char val; //stores received character. Needs to be global to perform continuous movement

//*********General SETUP: activate pins***********************************
void setup() {
 //start receiving serial infor
 Serial.begin(9600);
 //motor connections
 pinMode(MotorRight1, OUTPUT);  //
 pinMode(MotorRight2, OUTPUT);  //
 pinMode(MotorLeft1,  OUTPUT);  //
 pinMode(MotorLeft2,  OUTPUT);  //
 pinMode(MotorRightPWM, OUTPUT); //enable for right side motor
 pinMode(MotorLeftPWM, OUTPUT); //enable for right side motor
 irrecv.enableIRIn();      // start infrared decode
 myservo.write(degreesForward);       // will make head look in front

 //black track following
 pinMode(SensorLeft, INPUT);
 pinMode(SensorMiddle, INPUT);
 pinMode(SensorRight, INPUT);

 //Ultra sonic
 //digitalWrite(2,HIGH); //what is this pin for?
 pinMode(echoPin, INPUT);
 pinMode(triggerPin, OUTPUT);
 myservo.attach(servoPin);
}

//**************Movement functions******************************
void advance(int d) { //go straight
 digitalWrite(MotorRight1, HIGH);
 digitalWrite(MotorRight2, LOW);
 digitalWrite(MotorLeft1, HIGH);
 digitalWrite(MotorLeft2, LOW);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);
 delay(d * 10);
}
void right(int d) { //turn right (single wheel)
 digitalWrite(MotorLeft1, LOW);
 digitalWrite(MotorLeft2, HIGH);
 digitalWrite(MotorRight1, LOW);
 digitalWrite(MotorRight2, LOW);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);
 delay(d * 10);
}
void left(int d) {//turn left(single wheel)
 digitalWrite(MotorRight1, LOW);
 digitalWrite(MotorRight2, HIGH);
 digitalWrite(MotorLeft1, LOW);
 digitalWrite(MotorLeft2, LOW);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);
 delay(d * 10);
}
void turnR(int d) {//turn right (two wheels)
 digitalWrite(MotorRight1, HIGH);
 digitalWrite(MotorRight2, LOW);
 digitalWrite(MotorLeft1, LOW);
 digitalWrite(MotorLeft2, HIGH);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);  
 delay(d * 10);
}
void turnL(int d) {//turn left (two wheels)
 digitalWrite(MotorRight1, LOW);
 digitalWrite(MotorRight2, HIGH);
 digitalWrite(MotorLeft1, HIGH);
 digitalWrite(MotorLeft2, LOW);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);
 delay(d * 10);
}
void stopp(int d) { //stop
 digitalWrite(MotorRight1, LOW);
 digitalWrite(MotorRight2, LOW);
 digitalWrite(MotorLeft1, LOW);
 digitalWrite(MotorLeft2, LOW);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);  
 delay(d * 10);
}
void back(int d) { //go back
 digitalWrite(MotorRight1, LOW);
 digitalWrite(MotorRight2, HIGH);
 digitalWrite(MotorLeft1, LOW);
 digitalWrite(MotorLeft2, HIGH);
 analogWrite(MotorRightPWM, iSpeed);
 analogWrite(MotorLeftPWM, iSpeed);  
 delay(d * 10);
}

//************Ultrasonic distance calculator*************************************
//detect distance for given angles and print char + direction
float getDistance(int degrees, char dir) {
 myservo.write(degrees);
 digitalWrite(triggerPin, LOW); // ultrasonic echo low level in 2us
 delayMicroseconds(2);
 digitalWrite(triggerPin, HIGH); // ultrasonic echo high level in 10us, at least 10us
 delayMicroseconds(10);
 digitalWrite(triggerPin, LOW); // ultgrasonic echo low level
 float distance = pulseIn(echoPin, HIGH); // read time
 distance = distance / 5.8 / 10; // turn time to distance
 Serial.print(dir); //
 Serial.print(" distance: "); //
 Serial.print(int(distance)); //  output distance (mm)
 Serial.print("\n");
 return distance;
}
//*************Ultrasonic direction decision making******************************
//measurements three angles (front, left, right
int getDirectionFromdetection() {
 int Fspeedd = 0; // front distance
 int Rspeedd = 0; // right distance
 int Lspeedd = 0; // left distance
 int delay_time = 250; //
 int directionn =0;
 
 //get front distance
 Fspeedd = getDistance(degreesForward, 'F');

 // if distance is less than 10mm
 if (Fspeedd < 10) {
   stopp(1); //  clear output
   directionn = Bgo;
 }
 // if distance less than 25 mm
 else if (Fspeedd < 25) {
   stopp(1); // clear output
   Lspeedd = getDistance(degreesLeft, 'L'); // detection distance on left side
   delay(delay_time); // waiting for the servo motor to become stable
   
   Rspeedd = getDistance(degreesRight, 'R'); // detection distance on right side
   delay(delay_time); // waiting for servo motor to be stable

   // if left distance greater than right
   if (Lspeedd > Rspeedd) {
     directionn = Lgo; // go left
   }

   if (Lspeedd <= Rspeedd) {//if left distance less than right
     directionn = Rgo; //go right
   }

   if (Lspeedd < 15 && Rspeedd < 15) { //if distance less 10mm both right and left
     directionn = Bgo; //go back
   }
 }
 else {
   directionn = Fgo; //go straight
 }
 return directionn;
}

void autoRunUsingUltraSonic() {
 bool stopPressed;
 int directionn = 0; // front=8, back=2, left=4, right=6
 while (IRAutorun) {
   myservo.write(80); // make the servo motor reset
   directionn = getDirectionFromdetection();
   stopPressed = stopCommandPressed();
   if (stopPressed) {
     break;
   }
   else if (directionn == Fgo) { //go straight
     infrared.value = 0;
     advance(5); //
     Serial.print(" Advance "); //
     Serial.print(" ");
   }
   else if (directionn == Bgo) { //go back
     infrared.value = 0;
     back(8); //
     turnL(3); //
     Serial.print(" Reverse "); //
   }
   else if (directionn == Rgo) { //turn right
     infrared.value = 0;
     back(1);
     turnR(60); //
     Serial.print(" Right "); //
   }
   else if (directionn == Lgo) { //turn left
     infrared.value = 0;
     back(1);
     turnL(60);
     Serial.print(" Left ");
   }
 }
 infrared.value = 0;
}

//*************************Bluetooth functionality***********************
//Bluetooth commands
void bluetoothCommand() {
 if (Serial.available()) { //check if bluetooth command available
   val = Serial.read();
   Serial.write(val);
 }
 if (val == 'F') { // Forward
   advance(10);
 }
 else if (val == 'S') { // Stop Forward
   stopp(10) ;
   val = Serial.read(); //read value again, otherwise can't continu with infrared
 }
 else if (val == 'B') { // Backwards
   back(10);
 }
 else if (val == 'R') { // Right
   turnL(10);
 }
 else if (val == 'L') { // Left
   turnR(10);
 }
 else if (val == 's') { // Stop, not used though
   stopp(10 ) ;
 }
 else if (int(val) >= 49 && int(val) <= 57) { //set speed
   iSpeed = (int(val)-48)*26;
   Serial.println("Speed set to: " + iSpeed);
 }
 else if (val == 'q') { //set speed
   iSpeed = 255;
   digitalWrite(LedPin,HIGH);  
   Serial.println("Speed set to: " + iSpeed);  
 }
 else if (val == 'W') {
   digitalWrite(LedPin,HIGH);
 }
 else if (val == 'w') {
   digitalWrite(LedPin,LOW);
 }
}

//Check if stop command on remote is pressed (button 5)
bool stopCommandPressed(){
 bool stopPressed = false;
 if (irrecv.decode(&infrared)) {
   irrecv.resume();
   Serial.println(infrared.value, HEX);
   if (infrared.value == IRstop) {
     stopp(10);
     stopPressed = true;
   }
 }
 return stopPressed;
}

void followBlackLine() {
 bool stopPressed;
 int SL;  //sensor left
 int SM;  //sensor middle
 int SR;  //sensor right
 while (IRcny70) {
   SL = digitalRead(SensorLeft);
   SM = digitalRead(SensorMiddle);
   SR = digitalRead(SensorRight);

   if (SM == HIGH) {//middle sensor in black area
     if (SL == LOW & SR == HIGH) {//left sensor in black area, right sensor in white, turn left
       left(50);
     }
     else if (SR == LOW & SL == HIGH) {//left white, right black, run right
       right(50);
     }
     else { // left and right both in white, go straight
       advance(50);
     }
   }
   // middle sensor in white area
   else {
     if (SL == LOW & SR == HIGH) { // left black ,right white, turn left
       left(50);
     }
     else if (SR == LOW & SL == HIGH) {
       right(50);
     }
     else {  //left and right both in white, stop
       stopp(50);
     }
   }
   stopPressed = stopCommandPressed();
   if (stopPressed) {
     break;
   }
 }
 infrared.value = 0;  
}

//**************************************MAIN LOOP***************************************
void loop() {
 //bluetooth commands
 bluetoothCommand();
 //************************************normal remote control mode ********
 // decoding success 'receive infrared signal
 if (irrecv.decode(&infrared))  {        
   if (infrared.value == IRfront) {
     advance(0); //go straigt
   }
   else if (infrared.value ==  IRback) {
     back(0); //go back
   }
   else if (infrared.value == IRturnright) {
     turnR(0); // go right
   }
   else if (infrared.value == IRturnleft) {
     turnL(0); // go left
   }
   else if (infrared.value == IRstop) {//stop
     stopp(0);
   }
   //********************follow black line********cny70 automatic mode********
   else if (infrared.value == IRcny70) {
     followBlackLine();
   }
   //***********************ultrasonic automatic mode***************************
   else if (infrared.value == IRAutorun ) {
     autoRunUsingUltraSonic();
     myservo.write(degreesForward);       // will make head look in front
   }
   //********************wait a little before continuing**************************
   irrecv.resume();
   delay(300);
 }
 else {
   stopp(0);
 }
}
Witam wszystkich,

Przygode z Arduino zacząłem dość niedawno od pojazdu o dwóch funkcjonalnościach tj. sterowanie poprzez Bletooth oraz tryb autonomiczny poprzez czujnik ultradźwiękowy, zdjęcie pojazdu w załączniku.
     

Może obrałem złą drogę ale dorwałem kod który obsługuje pojazd pod kątem irdy, line trackera, modułu bluetooth oraz wspomnianego czujnika ultradźwiekowego. Kod dla mnie jako osoby początkującej jest nie do końca zrozumiały.
Podjąłby sie ktoś próby przerobienia go aby został tylko moduł Bluetooth oraz tryb autonomiczny oparty na czujniku ultradziekowym ? Pomogłoby mi to stawiać pierwsze kroki oraz stopniowo modyfikować pojazd.

Z góry dziękuje za pomoc

ps. kod zamieszczam w załączniku
 
Odpowiedź
#2
(16-01-2017, 12:06)arkadius657 napisał(a): Podjąłby sie ktoś próby przerobienia go aby został tylko moduł Bluetooth oraz tryb autonomiczny oparty na czujniku ultradziekowym ? Pomogłoby mi to stawiać pierwsze kroki oraz stopniowo modyfikować pojazd.
Jeśli stawiasz pierwsze kroki to zacznij od dowolnego kursu a wtedy wszystko stopniowo przerobisz sam. Np: http://forbot.pl/blog/artykuly/programow...step-id936
Pomagam za darmo więc szanuj mój czas.
Wklejaj tekst a nie jego zdjęcie.
Nie pisz następnego postu jak nie odpowiedziałeś na poprzedni.
Jak mądrze zadawać pytania
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości