#include <Arduino.h>
#include "TeensyThreads.h"
#include <NewPing.h>
#include <Streaming.h>
#include <vector>
#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
/* Set the delay between fresh samples for BNO055*/
#define BNO055_SAMPLERATE_DELAY_MS (100)
Adafruit_BNO055 bno = Adafruit_BNO055(55);
#define rad2deg 57.2957795131
#define deg2rad 0.01745329251
#define m2ft 3.280839895
float yar_heading, pitch, roll;
float gyroz, accelx, accely;
#define telem Serial
unsigned int pingSpeed = 50; // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second.
#define SONAR_NUM 4 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 45 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).
unsigned int cm[SONAR_NUM]; // Where the ping distances are stored.
uint8_t currentSensor = 0; // Keeps track of which sensor is active.
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
NewPing sonar[SONAR_NUM] = {
NewPing(27, 26, MAX_DISTANCE), //lower left sensor
NewPing(36, 35, MAX_DISTANCE), //front middle
NewPing(30, 29, MAX_DISTANCE), //lower rigth sensro
NewPing(34, 33, MAX_DISTANCE) // Each sensor's trigger pin, echo pin, and max distance to ping.
};
//IR Sensor Pins
const int leftIRsensor = A22; //Front
const int rightIRsensor = A2; //Rear
int frtIRdistance, rearIRdistance;
int max_IR_distance = 200;
int id1, id2, id3;
ThreadWrap(Serial, SerialX);
#define Serial ThreadClone(SerialX)
void my_priv_func1(){
while(1){
for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
if (millis() >= pingTimer[i]) { // Is it this sensor's time to ping?
pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Set next time this sensor will be pinged.
if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
sonar[currentSensor].timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance).
currentSensor = i; // Sensor being accessed.
cm[currentSensor] = 0; // Make distance zero in case there's no ping echo for this sensor.
sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
}
threads.delay(10);
for (uint8_t i = 0; i < SONAR_NUM; i++) {
Serial.print(i);
Serial.print("=");
Serial.print(cm[i]);
Serial.print("cm ");
}
Serial.println();
}
}
}
void my_priv_func2(){
while(1){
int sum = 0;
for (int i=0; i<3; i++) {
int sensor_value = analogRead(leftIRsensor); //read the sensor value
if(sensor_value < 100){
sensor_value = 100;
}
sum = sum + sensor_value;
threads.delay(5);
}
frtIRdistance = 27495 * pow(sum/3,-1.36); //convert readings to distance(cm)
sum = 0;
for (int i=0; i<3; i++) {
int sensor_value = analogRead(rightIRsensor); //read the sensor value
if(sensor_value < 100){
sensor_value = 100;
}
sum = sum + sensor_value;
threads.delay(5);
}
rearIRdistance = 25445 * pow(sum/3,-1.362); //convert readings to distance(cm)
telem << "IR Distances: " << frtIRdistance << " -- " << rearIRdistance << endl;
}
}
void my_priv_func3(){
while(1){
sensors_event_t sensor;
bno.getEvent(&sensor);
imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);
imu::Vector<3> accel_linear = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
imu::Vector<3> rot_rate = bno.getVector(Adafruit_BNO055::VECTOR_GYROSCOPE);
roll = (float)sensor.orientation.y;
pitch = (float)sensor.orientation.z;
yar_heading = (float)sensor.orientation.x;
gyroz = (float) rot_rate.z() * rad2deg;
accelx = (float) accel_linear.x() * m2ft;
accely = (float) accel_linear.y() * m2ft;
//telem << roll << "\t" << pitch << "\t" << yar_heading << endl;
//telem << "Changed heading: " << yar_heading << endl;
threads.delay(BNO055_SAMPLERATE_DELAY_MS);
telem << -roll << "," << -pitch << "," << yar_heading << endl;
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Wire.begin(400000);
//ctx_switch_timer.begin(ctx_switch_timer_isr, 100);
//context_timer.priority(254);
//context_timer.begin(context_switch_isr, 100);
BNO055_Init();
delay(5000);
//Serial.print("Thread start ");
//if (threads.setMicroTimer(5)==0) { // ticks every 10 microseconds!
// Serial.println("Failed to set timer!");
//}
pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting.
for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
id1 = threads.addThread(my_priv_func1);
id2 = threads.addThread(my_priv_func2);
id3 = threads.addThread(my_priv_func3);
threads.setTimeSlice(0, 1);
threads.setTimeSlice(id1, 20);
threads.setTimeSlice(id2, 1);
threads.setTimeSlice(id3, 50);
if (threads.getState(id1) == Threads::RUNNING) Serial.println("Sonar thread started");
if (threads.getState(id2) == Threads::RUNNING) Serial.println("IR thread started");
if (threads.getState(id3) == Threads::RUNNING) Serial.println("BNO055 thread started");
}
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
/* for (uint8_t i = 0; i < SONAR_NUM; i++) {
Serial.print(i);
Serial.print("=");
Serial.print(cm[i]);
Serial.print("cm ");
}
Serial.println();
telem << "IR Distances: " << frtIRdistance << " -- " << rearIRdistance << endl;
telem << -roll << "," << -pitch << "," << yar_heading << endl;
*/
}
void loop() {
oneSensorCycle();
}
void echoCheck() { // If ping received, set the sensor distance to array.
if (sonar[currentSensor].check_timer())
cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}