2020-09-23

//---------------------------------------------------------------------------

//This Arduino sketch accompanies the OpenBot Android application.

//

//The sketch has the following functinonalities:

//- receive control commands from Android application (USB serial)

//. - produce low-level controls (PWM) for the vehicle

//- toggle left and right indicator signals

//- wheel odometry based on optical speed sensors

//- estimate battery voltage via voltage divider

//- estimate distance based on sonar sensor

//- send sensor readings to Android application (USB serial)

//

//Dependencies (if sonar is required):

//- NewPing library by Tim Eckel (Install via Tools --> Manage Libraries)

//

//By Matthias Mueller, Intelligent Systems Lab, 2020

//---------------------------------------------------------------------------

//PIN_PWM1,PIN_PWM2,PIN_PWM3,PIN_PWM4      Low-level control of left DC motors via PWM

//PIN_SPEED_L, PIN_SPEED_R                Measure left and right wheel speed

//PIN_VIN                                  Measure battery voltage via voltage divider

//PIN_TRIGGER                              Arduino pin tied to trigger pin on ultrasonic sensor.

//PIN_ECHO                                Arduino pin tied to echo pin on ultrasonic sensor.

//MAX_DISTANCE                            Maximum distance we want to ping for (in centimeters).

//PIN_LED_RL, PIN_LED_RR                  Toggle left and right rear LEDs (indicator signals)

//------------------------------------------------------//

//DEFINITIONS

//------------------------------------------------------//

#defineDIY0

#definePCB1

#defineHAS_SONAR1

//Setup the OpenBot version

#defineOPENBOTDIY

#if(OPENBOT == DIY)

#definePIN_PWM15

#definePIN_PWM26

#definePIN_PWM39

#definePIN_PWM410

#definePIN_SPEED_L2

#definePIN_SPEED_R3

#definePIN_VINA7

#definePIN_TRIGGER4

#definePIN_ECHO4

#definePIN_LED_RL7

#definePIN_LED_RR8

#elif(OPENBOT == PCB)

#definePIN_PWM110

#definePIN_PWM29

#definePIN_PWM35

#definePIN_PWM46

#definePIN_SPEED_L2

#definePIN_SPEED_R4

#definePIN_VINA7

#definePIN_TRIGGER3

#definePIN_ECHO3

#definePIN_LED_RL7

#definePIN_LED_RR8

#endif

//------------------------------------------------------//

//INITIALIZATION

//------------------------------------------------------//

#ifHAS_SONAR

//Sonar sensor

#include<NewPing.h>

constintMAX_DISTANCE =300;

NewPingsonar(PIN_TRIGGER, PIN_ECHO, MAX_DISTANCE);//NewPing setup of pins and maximum distance.

unsignedintping_interval =100;//How frequently are we going to send out a ping (in milliseconds).

unsignedlongping_timeout;//Timeout (in milliseconds). After timeout, distance is set to maximum.

unsignedlongping_time;//Holds the next ping time.

unsignedintdistance_cm = MAX_DISTANCE;

#else

#include<limits.h>

unsignedintdistance_cm = UINT_MAX;

#endif

//Vehicle Control

intctrl_left =0;

intctrl_right =0;

//Voltage measurement

unsignedintcounter_voltage =0;

constunsignedintvin_array_sz =100;

unsignedintvin_array[vin_array_sz]={0};

//Speed sensors

constunsignedlongignoremilli =0;

unsignedlongoldtime_left =0;

unsignedlongcurtime_left =0;

unsignedlongoldtime_right =0;

unsignedlongcurtime_right =0;

intcounter_left =0;

intcounter_right =0;

//Indicator Signal

constunsignedlongindicator_interval =500;

unsignedlongindicator_time =0;

intindicator_val =0;

boolindicator_left =0;

boolindicator_right =0;

boolctrl_rx =0;

boolindicator_rx =0;

//Serial communication

constunsignedlongsend_interval =1000;

unsignedlongsend_time =0;

String inString ="";

//------------------------------------------------------//

//SETUP

//------------------------------------------------------//

voidsetup()

{

//Outputs

pinMode(PIN_PWM1,OUTPUT);

pinMode(PIN_PWM2,OUTPUT);

pinMode(PIN_PWM3,OUTPUT);

pinMode(PIN_PWM4,OUTPUT);

pinMode(PIN_LED_RL,OUTPUT);

pinMode(PIN_LED_RR,OUTPUT);

//Inputs

pinMode(PIN_VIN,INPUT);

pinMode(PIN_SPEED_L,INPUT);

pinMode(PIN_SPEED_R,INPUT);

attachInterrupt(digitalPinToInterrupt(PIN_SPEED_L), speed_left, RISING);

attachInterrupt(digitalPinToInterrupt(PIN_SPEED_R), speed_right, RISING);

Serial.begin(115200,SERIAL_8N1);//8 data bits, no parity, 1 stop bit

send_time =millis() + send_interval;//wait for one interval to get readings

#ifHAS_SONAR

ping_time =millis();

#endif

}

//------------------------------------------------------//

//LOOP

//------------------------------------------------------//

voidloop() {

//Measure voltage

vin_array[counter_voltage%vin_array_sz] =analogRead(PIN_VIN);

  counter_voltage++;

#ifHAS_SONAR

//Measure distance every ping_interval

if(millis() >= ping_time) {//Ping if it's time

ping_timeout = ping_time +2* MAX_DISTANCE *10/343+1;//Set ping timeout.

ping_time += ping_interval;//Set the next ping time.

sonar.ping_timer(echoCheck);//Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status.

  }

#endif


//Write voltage to serial every send_interval

if(millis() >= send_time)

  {

sendVehicleData();

    send_time += send_interval;

  }

//Check indicator signal every indicator_interval

if(millis() >= indicator_time)

  {

updateindicator();

    indicator_time += indicator_interval;

  }

if(Serial.available() >0) {

charinChar = Serial.read();

if(ctrl_rx) {

processCtrlMsg(inChar);

    }

elseif(indicator_rx) {

processindicatorMsg(inChar);

    }

else{

checkForMsg(inChar);

    }

  }

}

//------------------------------------------------------//

//FUNCTIONS

//------------------------------------------------------//

floatgetVoltage() {

unsignedlongarray_sum =0;

unsignedintarray_size =min(vin_array_sz,counter_voltage);

for(unsignedintindex=0;index< array_size;index++)

  {

array_sum += vin_array[index];

  }

returnfloat(array_sum)/array_size/1023*4.04*5;

}

voidspeed_left() {

curtime_left =millis();

if( (curtime_left - oldtime_left) > ignoremilli ) {

if(ctrl_left <0) {

      counter_left--;

    }

else{

      counter_left++;

    }

    oldtime_left = curtime_left;

  }

}

voidspeed_right() {

curtime_right =millis();

if( (curtime_right - oldtime_right) > ignoremilli ) {

if(ctrl_right <0) {

      counter_right--;

    }

else{

      counter_right++;

    }

    oldtime_right = curtime_right;

  }

}

voidprocessCtrlMsg(charinChar) {

//Serial.write(inChar);

//comma indicates that inString contains the left ctrl

if(inChar ==',') {

ctrl_left = inString.toInt();

if(ctrl_left <0) {

analogWrite(PIN_PWM1,-ctrl_left);

analogWrite(PIN_PWM2,0);

    }

elseif(ctrl_left >0) {

analogWrite(PIN_PWM1,0);

analogWrite(PIN_PWM2,ctrl_left);

    }

else{//Motor brake

analogWrite(PIN_PWM1,255);

analogWrite(PIN_PWM2,255);

    }

//clear the string for new input:

inString ="";

  }

//new line indicates that inString contains the right ctrl

elseif(inChar =='\n') {

ctrl_right = inString.toInt();//* 0.95;

if(ctrl_right <0) {

analogWrite(PIN_PWM3,-ctrl_right);

analogWrite(PIN_PWM4,0);

    }

elseif(ctrl_right >0) {

analogWrite(PIN_PWM3,0);

analogWrite(PIN_PWM4,ctrl_right);

    }

else{//Motor brake

analogWrite(PIN_PWM3,255);

analogWrite(PIN_PWM4,255);

    }

//clear the string for new input:

inString ="";

//end of message

ctrl_rx =false;

  }

else{

//As long as the incoming byte

//is not a newline or comma,

//convert the incoming byte to a char

//and add it to the string

    inString += inChar;

  }

}

voidprocessindicatorMsg(charinChar)

{

//new line indicates that inString contains the indicator signal

if(inChar =='\n') {

indicator_val = inString.toInt();

//clear the string for new input:

inString ="";

//end of message

indicator_rx =false;

  }

else{

//As long as the incoming byte

//is not a newline

//convert the incoming byte to a char

//and add it to the string

    inString += inChar;

  }

}

voidcheckForMsg(charinChar)

{

switch(inChar) {

case'c':

ctrl_rx =true;

break;

case'i':

indicator_rx =true;

break;

  }

}

voidsendVehicleData()

{

Serial.print(getVoltage());

Serial.print(",");

Serial.print(counter_left);

Serial.print(",");

Serial.print(counter_right);

Serial.print(",");

Serial.print(distance_cm);

Serial.println();

counter_left =0;

counter_right =0;

}

voidupdateindicator()

{

switch(indicator_val) {

case-1:

      indicator_left = !indicator_left;

      indicator_right = LOW;

break;

break;

case0:

      indicator_left = LOW;

      indicator_right = LOW;

break;

case1:

      indicator_left = LOW;

      indicator_right = !indicator_right;

break;

  }

digitalWrite(PIN_LED_RL, indicator_left);

digitalWrite(PIN_LED_RR, indicator_right);

}

#ifHAS_SONAR

voidechoCheck() {//Timer2 interrupt calls this function every 24uS.

if(sonar.check_timer()) {//Check ping status

distance_cm = sonar.ping_result/ US_ROUNDTRIP_CM;//Ping returned in uS, convert to cm.

  }

elseif(millis() >= ping_timeout) {

    distance_cm = MAX_DISTANCE;

  }

}

#endif

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容