The rapid rise of edge AI capabilities on embedded targets has proven that relatively low-resource microcontrollers are capable of some incredible things. And with the recent release of the Arduino UNO R4 with its Renesas RA4M1 processor, the ceiling has gotten even higher as YouTuber and maker Nikodem Bartnik has demonstrated with his lidar-equipped mobile robot.
Bartnik’s project started with a simple question of whether it’s possible to teach a basic robot how to navigate around obstacles using only lidar instead of the more resource-intensive computer vision techniques employed by most other platforms. The chassis and hardware, including two DC motors, an UNO R4 Minima, a Bluetooth® module, and SD card, were constructed according to Open Robotic Platform (ORP) rules so that others can easily replicate and extend its functionality. After driving through a series of courses in order to collect a point cloud from the spinning lidar sensor, Bartnik imported the data and performed a few transformations to greatly minify the classification model.
Once trained, the model was exported with help from the micromlgen Python package and loaded onto the UNO R4. The setup enables the incoming lidar data to be classified as the direction in which the robot should travel, and according to Bartnik’s experiments, this approach worked surprisingly well. Initially, there were a few issues when navigating corners and traveling through a figure eight track, but additional training data solved it and allowed the vehicle to overcome a completely novel course at maximum speed.
Firefighting is a dangerous profession, but it is possible to mitigate some of that danger with good data. When firefighters entered a burning building, their biggest fear is the unknown. They don’t know if they can trust the structural integrity of the building, if there is a pocket of toxic or explosive gas, or how to navigate the interior to find casualties. As part of a project called HelpResponder, a team of researchers from Universidad Rey Juan Carlos and Universidad Autónoma de Madrid created a robot that can enter a building to gather the data firefighters need to do their job safely.
This robot, which is a mid-sized rover, can operate via manual control or in an autonomous mode. In both cases, its job is to explore buildings, either during a fire or after a disaster, to map the interior and find hazards. Its camera system allows for visual detection, but it also has a host of integrated sensors for detecting elevated temperatures, gas pockets, and more. With that information, firefighters can then enter the building and rescue anyone trapped inside while avoiding hazardous areas or bringing the equipment necessary to deal with them.
Control and monitoring happens on two levels. At the high level, a Raspberry Pi 4 Model B single-board computer records video, handles mapping operations, and coordinates autonomous navigation. At the low level, an Arduino UNO WiFi Rev.2 collects incoming sensor data and controls the motor driver. The onboard sensors include a temperature/humidity sensor, an air quality sensor, and ultrasonic sensors for navigation. Thanks to a modular design, additional hardware can be added to fit specific scenarios.
For this year’s Hackaday Prize, hacker “Ulysse” has designed an autonomous beach art rover using an Arduino Mega and a pair of Micros.
While walking along the shore, the footprints you leave behind are mildly interesting, and perhaps you might go to the effort of scraping a pattern in the sand if you were feeling rather creative. If, however, you wanted to make drawings on a massive scale, Ulysse’s robot “Pablo Odysseus” looks like an elegant solution.
The Arduino-powered rover uses two wheelchair motors to propel it along the beach, as well as a rake to leave a mark as to where it’s been. Navigation is provided by a GNSS receiver (a more general term for “GPS”), a digital compass, and an odometer set up on each of the motors. Meanwhile, USB dongles enable it to communicate wirelessly with a smartphone and laptop.
Now, Ulysse can simply program in an artistic pattern, and Pablo will take care of the rest! You can see more about this project on Hackaday.io and GitHub.
This is a repost of a previous project. I am still working to get the older post back online from when we upgraded Wordpress.
The robot was basically built using a Parallax Boe Bot chassis. Rather than using the Basic Stamp we added an Arduino with a proto shield to control the robot functions.
You can use any type of chassis for this project. The robot moves about using a ping sonar and IR sensors to avoid running into any objects. As you can see in the video, it was a bit thrown off by our kitten. We added additional items such as a wireless camera that sends audio/video back to our TV.The original design for this was created by an Instructable’s member and can be found here.
The standard servo will be used to mount the Ping Rangefinder. This will give you a back and forth sweep motion as the robot travels around. The two continuous rotation servos are used for the wheels. You do not need to use the Parallax brand of servos, other brands will work. You may have to adjust the PWM values in the source code to go with the servos you are using.
The Arduino hook up is pretty simple. You will have the following:
Pin (Analog) 0: Left Sensor
Pin (Analog) 1: Center Sensor
Pin (Analog) 2: Right Sensor
Pin 5: Pan Servo
Pin 6: Left Drive Servo
Pin 7: Ultrasonic Rangefinder ( ‘Ping)))’ )
Pin 9: Right Drive Servo
Pin 11: Piezo Speaker
Shield Close-up
Radioshack sells an RC car battery as well as connector repair kit. You can solder the repair kit connector onto the shield, and then be able to hook up your battery to power the servos with. You can use a separate battery holder to power the Arduino.
Make all your connections onto the shield. This way everything can remain in place if you need to use your Arduino for something else and save you from needing to tear apart everything.
for power to the shield, you won’t need any extra filter capacitors since the 5V switching regulator has them built in. We used a small project box to hold the battery in place, and was able to attach the wireless camera on top of it.
The Arduino and camera are power source 1, while the servos and sensors are power source 2 (the RC battery). A small piece of PVC pipe mounted onto a cable clip will help you to keep your wires all organized to a central point and be less likely to get caught or tangled up into something as the robot is moving around.
Arduino Sketch
// Begin Robot Codeint micVal;
int cdsVal;
int irLval; // Left IRint irCval; // Center IRint irRval; // Right IRint i; // Generic Counterint x; // Generic Counterint PLval; // Pulse Width for Left Servoint PRval; // Pulse Width for Right Servoint cntr; // Generic Counter Used for Determining amt. of Object Detectionsint counter; // Generic Counterint clrpth; // amt. of Milliseconds Of Unobstructed Pathint objdet; // Time an Object was Detectedint task; // Routine to Follow for Clearest Pathint pwm; // Pulse Width for Pan Servoboolean add; // Whether to Increment or Decrement PW Value for Pan Servoint distance; // Distance to Object Detected via Ultrasonic Rangerint oldDistance; // Previous Distance Value Read from Ultrasonic Rangerfloat scale = 1.9866666666666666666666666666667; // *Not Currently Used*int LeftPin = 6; // Left Servoint RightPin = 9; // Right Servoint PiezoPin = 11; // Piezoint PingServoPin = 5; // Pan Servoint irLPin = 0; // Analog 0; Left IRint irCPin = 1; // Analog 1; Center IRint irRPin = 2; // Analog 2; Right IRint ultraSoundSignal = 7; // Ultrasound signal pinint val = 0; // Used for Ultrasonic Rangerint ultrasoundValue = 0; // Raw Distance Valint oldUltrasoundValue; // *Not used*int pulseCount; // Generic Counterint timecount = 0; // Echo counterint ledPin = 13; // LED connected to digital pin 13
#define BAUD 9600
#define CmConstant 1/29.034
voidsetup() {
Serial.begin(9600);
pinMode(PiezoPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(LeftPin, OUTPUT);
pinMode(RightPin, OUTPUT);
pinMode(PingServoPin, OUTPUT);
pinMode(irLPin, INPUT);
pinMode(irCPin, INPUT);
pinMode(irRPin, INPUT);
for(i = 0; i < 500; i++) {
digitalWrite(PiezoPin, HIGH);
delayMicroseconds(1000);
digitalWrite(PiezoPin, LOW);
delayMicroseconds(1000);
}
for(i = 0; i < 20; i++) {
digitalWrite(PingServoPin, HIGH);
delayMicroseconds(655 * 2);
digitalWrite(PingServoPin, LOW);
delay(20);
}
ultrasoundValue = 600;
i = 0;
}
voidloop()
{
//Scan();
Look();
Go();
}
void Look() {
irLval = analogRead(irLPin);
irCval = analogRead(irCPin);
irRval = analogRead(irRPin);
//if(counter > 10) {//counter = 0;//readPing();//}if(irLval > 200) {
PLval = 850;
PRval = 820;
x = 5;
cntr = cntr + 1;
clrpth = 0;
objdet = millis();
}
elseif(irCval > 200) {
PLval = 850;
PRval = 820;
x = 10;
cntr = cntr + 1;
clrpth = 0;
objdet = millis();
}
elseif(irRval > 200) {
PLval = 650;
PRval = 620;
x = 5;
cntr = cntr + 1;
clrpth = 0;
objdet = millis();
}
else {
x = 1;
PLval = 850;
PRval = 620;
counter = counter + 1;
clrpth = (millis() - objdet);
if(add == true) {
pwm = pwm + 50;
}
elseif(add == false) {
pwm = pwm - 50;
}
if(pwm < 400) {
pwm = 400;
add = true;
}
if(pwm > 950) {
pwm = 950;
add = false;
}
digitalWrite(PingServoPin, HIGH);
delayMicroseconds(pwm * 2);
digitalWrite(PingServoPin, LOW);
delay(20);
readPing();
if(ultrasoundValue < 500) {
cntr = cntr + 1;
switch(pwm) {
case 400:
x = 7;
PLval = 650;
PRval = 650;
Go();
break;
case 500:
x = 10;
PLval = 650;
PRval = 650;
Go();
break;
case 600:
x = 14;
PLval = 850;
PRval = 850;
Go();
break;
case 700:
x = 10;
PLval = 850;
PRval = 850;
Go();
break;
case 950:
x = 7;
PLval = 850;
PRval = 850;
Go();
break;
}
}
}
//Serial.print("clrpth: ");//Serial.println(clrpth);//Serial.print("objdet: ");//Serial.println(objdet);//Serial.print("cntr: ");//Serial.println(cntr);if(cntr > 25 && clrpth < 2000) {
clrpth = 0;
cntr = 0;
Scan();
}
}
void Go() {
for(i = 0; i < x; i++) {
digitalWrite(LeftPin, HIGH);
delayMicroseconds(PLval * 2);
digitalWrite(LeftPin, LOW);
digitalWrite(RightPin, HIGH);
delayMicroseconds(PRval * 2);
digitalWrite(RightPin, LOW);
delay(20);
}
}
void readPing() { // Get Distance from Ultrasonic Ranger
timecount = 0;
val = 0;
pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output/* Send low-high-low pulse to activate the trigger pulse of the sensor * ------------------------------------------------------------------- */digitalWrite(ultraSoundSignal, LOW); // Send low pulsedelayMicroseconds(2); // Wait for 2 microsecondsdigitalWrite(ultraSoundSignal, HIGH); // Send high pulsedelayMicroseconds(5); // Wait for 5 microsecondsdigitalWrite(ultraSoundSignal, LOW); // Holdoff/* Listening for echo pulse * ------------------------------------------------------------------- */pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
val = digitalRead(ultraSoundSignal); // Append signal value to valwhile(val == LOW) { // Loop until pin reads a high value
val = digitalRead(ultraSoundSignal);
}
while(val == HIGH) { // Loop until pin reads a high value
val = digitalRead(ultraSoundSignal);
timecount = timecount +1; // Count echo pulse time
}
/* Writing out values to the serial port * ------------------------------------------------------------------- */
ultrasoundValue = timecount; // Append echo pulse time to ultrasoundValue//serialWrite('A'); // Example identifier for the sensor//printInteger(ultrasoundValue);//serialWrite(10);//serialWrite(13);/* Lite up LED if any value is passed by the echo pulse * ------------------------------------------------------------------- */if(timecount > 0){
digitalWrite(ledPin, HIGH);
}
}
void Scan() { // Scan for the Clearest Path
oldDistance = 30;
task = 0;
for(i = 1; i < 5; i++) {
switch(i) {
case 1:
//Serial.println("Pos. 1");
pwm = 1125; /// incr. by 100 from 1085
break;
case 2:
//Serial.println("Pos. 2");
pwm = 850; //// increased by 100 from 850
break;
case 3:
//Serial.println("Pos. 3");
pwm = 400;
break;
case 4:
//Serial.println("Pos. 4");
pwm = 235;
break;
}
for(pulseCount = 0; pulseCount < 20; pulseCount++) { // Adjust Pan Servo and Read USRdigitalWrite(PingServoPin, HIGH);
delayMicroseconds(pwm * 2);
digitalWrite(PingServoPin, LOW);
readPing();
delay(20);
}
distance = ((float)ultrasoundValue * CmConstant); // Calculate Distance in Cmif(distance > oldDistance) { // If the Newest distance is longer, replace previous reading with it
oldDistance = distance;
task = i; // Set task equal to Pan Servo Position
}
}
//Serial.print("Task: ");//Serial.println(task);//Serial.print("distance: ");//Serial.println(distance);//Serial.print("oldDistance: ");//Serial.println(oldDistance);
distance = 50; // Prevents Scan from Loopingswitch(task) { // Determine which task should be carried outcase 0: // Center was clearest
x = 28;
PLval = (850);
PRval = (850);
Go();
break;
case 1: // 90 degrees Left was Clearest
x = 14;
PLval = (650);
PRval = (650);
Go();
break;
case 2: // 45 degrees left
x = 7;
PLval = (650);
PRval = (650);
Go();
break;
case 3: // 45 degrees right
x = 7;
PLval = (850);
PRval = (850);
Go();
break;
case 4: // 90 degrees right
x = 14;
PLval = (850);
PRval = (850);
Go();
break;
}
}
// End Robot Code
About
Planet Arduino is, or at the moment is wishing to become, an aggregation of public weblogs from around the world written by people who develop, play, think on Arduino platform and his son. The opinions expressed in those weblogs and hence this aggregation are those of the original authors. Entries on this page are owned by their authors. We do not edit, endorse or vouch for the contents of individual posts. For more information about Arduino please visit www.arduino.cc
You are currently browsing the archives for the Autonomous Robot category.