2021 PROJECTS

In this post, I will cover some projects I have worked on over the last few months and some projects I have planned for the future.

Bipedal Robot


I am currently busy building a bipedal robot based on this Instructables post by K.Biagini. I used his design as a foundation and added additional components and functionality (such as arms and a Piezo for sound).

I had to modify his 3D models to achieve what I wanted. Here are links to download my modified 3d Models:
– Body Extension (to fit in the extra components) – Link
– Modified Head – Link
– Arms – Link

Here is a list of all the electronic components used:
– 1x Arduino Nano
– 6x micro servos
– 2 x push buttons
– 1x mini toggle switch
– 1x 9v Battery
– 1x ultrasonic sensor (HC-SR04)
– 1x RGB LED
– 1x Piezo

These components are connected as follows:

Pinout configuration of Arduino Nano:

Pin NumberConnected Hardware
2Ultrasonic Sensor Echo Pin
3RGB LED Red Pin
4Push Button 1
5RGB LED Green Pin
6RGB LED Blue Pin
7Push Button 2
8Servo Signal Pin (Right Hip)
9Servo Signal Pin (Right Ankle)
10Servo Signal Pin (Left Hip)
11Piezo
12Servo Signal Pin (Left Ankle)
13Ultrasonic Sensor Trigger Pin
14 (A0)Servo Signal Pin (Left Arm)
15 (A1)Servo Signal Pin (Right Arm)

This is still an in-progress project and is not done, Especially from a coding perspective on the Arduino, but once I have completed this project, I will create a post containing the complete source code.

Rotary Control

I needed a rotary control for another project discussed below, so I decided to build one as per this Post on the Prusa Printers blog. It is based on an Arduino Pro Micro and uses Rotary Encoder Module.

I modified the code available on the Prusa blog to mimic keyboard WASD inputs. Turning the dial left and right will input A and D, respectively. Pressing in the dial control push button will switch to up and down inputs, thus turning the dial left and right will input W and S.
Here is the modified code (Based on Prusa Printers blog post code):

#include <ClickEncoder.h>
#include <TimerOne.h>
#include <HID-Project.h>

#define ENCODER_CLK A0 
#define ENCODER_DT A1
#define ENCODER_SW A2

ClickEncoder *encoder; // variable representing the rotary encoder
int16_t last, value; // variables for current and last rotation value
bool upDown = false;
void timerIsr() {
  encoder->service();
}

void setup() {
  Serial.begin(9600); // Opens the serial connection
  Keyboard.begin();
  encoder = new ClickEncoder(ENCODER_DT, ENCODER_CLK, ENCODER_SW); 

  Timer1.initialize(1000); // Initializes the timer
  Timer1.attachInterrupt(timerIsr); 
  last = -1;
} 

void loop() {  
  value += encoder->getValue();

  if (value != last) { 
    if (upDown)
    {
    if(last<value) // Detecting the direction of rotation
        Keyboard.write('s');
      else
        Keyboard.write('w');
    }
    else
    {
      if(last<value) // Detecting the direction of rotation
        Keyboard.write('d');
      else
        Keyboard.write('a');
    }
    last = value; 
    Serial.print("Encoder Value: "); 
    Serial.println(value);
  }

  // This next part handles the rotary encoder BUTTON
  ClickEncoder::Button b = encoder->getButton(); 
  if (b != ClickEncoder::Open) {
    switch (b) {
      case ClickEncoder::Clicked: 
        upDown = !upDown;
      break;      
      
      case ClickEncoder::DoubleClicked: 
        
      break;      
    }
  }

  delay(10); 
}

I use the rotary control with a Raspberry Pi to control a camera pan-tilt mechanism. Here is a video showing it in action:

I will cover the purpose of the camera as well as the configuration and coding related to the pan-tilt mechanism later in this post.

Raspberry Pi Projects

Raspberry Pi and TensorFlow lite

TensorFlow is a deep learning library developed by Google that allows for the easy creation and implementation of Machine Learning models. There are many articles available online on how to do this, so I will not focus on how to do this.

At a high level, I created a basic object identification model created on my windows PC and then converted the model to a TensorFlow lite model that can be run on a Raspberry pi 4. When the TensorFlow lite model is run on the Raspberry Pi, a video feed is shown of the attached Raspberry Pi camera, with green blocks around items that the model has identified with a text label of what the model believes the object is, as well as a numerical percentage which indicates the level of confidence the model has in the object identification.

I have attached a 3inch LCD screen (in a 3D printed housing) to the Raspberry Pi to show the video feed and object identification in real-time.

The Raspberry Pi Camera is mounted on a pan-tilt bracket which is controlled via two micro servos. As mentioned earlier, the pan-tilt mechanism is controlled via the dial control discussed earlier. The pan-tilt mechanism servos are driven by an Arduino Uno R3 connected to the Raspberry Pi 4 via USB. I initially connected servos straight to Raspberry Pi GPIO pins. However, this resulted in servo jitter. After numerous modifications and attempted fixes, I was not happy with the results, so I decided to use an Arduino Uno R3 to drive the servos instead and connect it to the Raspberry Pi Via USB. I have always found hardware interfacing significantly easier with Arduino and also the result more consistent.

Here is a diagram of how the servos are connected to the Arduino Uno R3:

Below is the Arduino source code I wrote to control the servos. Instructions are sent to the Arduino through serial communication via USB, and the servos are adjusted accordingly.

#include <Servo.h>
#define SERVO1_PIN A2
#define SERVO2_PIN A3

Servo servo1;
Servo servo2;
String direction;
String key;
int servo1Pos = 0;
int servo2Pos = 0;

void setup()
{
  servo1Pos = 90;
  servo2Pos = 90;
  Serial.begin(9600);
  servo1.attach(SERVO1_PIN);
  servo2.attach(SERVO2_PIN);

  servo1.write(30);
  delay(500);
  servo1.write(180);
  delay(500);
  servo1.write(servo1Pos);
  delay(500);
  servo2.write(30);
  delay(500);
  servo2.write(150);
  delay(500);
  servo2.write(servo2Pos);
  delay(500);
  Serial.println("Started");
  servo1.detach();
  servo2.detach();
}

String readSerialPort()
{
  String msg = "";
  if (Serial.available()) {
    delay(10);
    msg = Serial.read();
    Serial.flush();
    msg.trim();
    Serial.println(msg);
  }
  return msg;
}

void loop()
{
  direction = "";
  direction = readSerialPort();
  //Serial.print("direction : " + direction);
  key = "";

  if (direction != "")
  {
    direction.trim();
    key = direction;

    servo1.attach(SERVO1_PIN);
    servo2.attach(SERVO2_PIN);

    if (key == "97")
    {
      if (servo2Pos > 30)
      {
        servo2Pos -= 10;
      }
      servo2.write(servo2Pos);
      delay(500);
      Serial.print("A");
    }

    else if (key == "115")
    {
      if (servo1Pos < 180)
      {
        servo1Pos += 10;
      }
      servo1.write(servo1Pos);
      delay(500);
      Serial.print("S");
    }

    else if (key == "119")
    {
      if (servo1Pos > 30)
      {
        servo1Pos -= 10;
      }
      servo1.write(servo1Pos);
      delay(500);
      Serial.print("W");
    }

    else if (key == "100")
    {
      if (servo2Pos < 150)
      {
        servo2Pos += 10;
      }
      servo2.write(servo2Pos);
      delay(500);
      Serial.print("D");
    }

    delay(100);
    servo1.detach();
    servo2.detach();
  }

}

On the Raspberry Pi, the following Python script is used to transfer the rotary control input via serial communication to the Arduino:

# Import libraries
import serial
import time
import keyboard
import pygame

pygame.init()
screen = pygame.display.set_mode((1, 1))

with serial.Serial("/dev/ttyACM0", 9600, timeout=1) as arduino:
    time.sleep(0.1)
if arduino.isOpen():
    done = False
while not done:
    for event in pygame.event.get():
    if event.type == pygame.QUIT:
    done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
    arduino.write('s'.encode())

if event.key == pygame.K_w:
    arduino.write('w'.encode())

if event.key == pygame.K_a:
    arduino.write('a'.encode())

if event.key == pygame.K_d:
    arduino.write('d'.encode())
time.sleep(0.5)

arduino.Close();
print ("Goodbye")

The next thing I want to implement on this project is face tracking using TensorFlow lite with automated camera movement.

Raspberry Pi Zero W Mini PC

I built a tiny PC using a Raspberry Pi Zero W combined with a RII RT-MWK01 V3 wireless mini keyboard and a 5 inch LCD display for Raspberry Pi with a 3D printed screen stand.


It is possible to run Quake 1 on the Raspberry Pi Zero following the instructions in this GitHub, and it runs great.

Raspberry Pi Mini Server Rack

I have 3D printed a mini server rack and configured a four Raspberry Pi Cluster consisting of three raspberry Pi 3s and one Raspberry Pi 2. They are all networked via a basic five-port switch.

I am currently busy with a few different projects using the Pi cluster and will have some posts in the future going into some more details on these projects.

I developed a little Python application to monitor my different Raspberry Pis and show which ones are online (shown in green) and offline (shown in red).

The application pings each endpoint every 5 seconds, and it is also possible to click on an individual endpoint to ping it immediately. The list of endpoints is read from a CSV file, and it is easy to add additional endpoints. The UI is automatically updated on program startup with the endpoints listed in the CSV file.

Here is the Python source code of the application:

import PySimpleGUI as sg
import csv
import time
import os
from apscheduler.schedulers.background import BackgroundScheduler


def ping(address):
    response = os.system("ping -n 1 " + address)
    return response


def update_element(server):
    global window
    global layout
    response = ping(server.address)
    if response == 0:
        server.status = 1
        window.Element(server.name).Update(button_color=('white', 'green'))
        window.refresh()
    else:
        server.status = 0
        window.Element(server.name).Update(button_color=('white', 'red'))
        window.refresh()


def update_window():
    global serverList
    for server in serverlist:
        update_element(server)


class server:
    def __init__(self, name, address, status):
        self.name = name
        self.address = address
        self.status = status


serverlist = []

with open('servers.csv') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            line_count += 1
        else:
            serverlist.append(server(row[0], row[1], 0))
            line_count += 1

layout = [
    [sg.Text("Server List:")],
]

for server in serverlist:
    layout.append([sg.Button('%s' % server.name, 
                    button_color=('white', 'orange'), 
                    key='%s' % server.name)])

window = sg.Window(title="KillerRobotics Server Monitor", 
                    layout=layout, margins=(100, 30))
window.finalize()
scheduler = BackgroundScheduler()
scheduler.start()

scheduler.add_job(update_window, 'interval', seconds=5, id='server_check_job')

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        scheduler.remove_all_jobs()
        scheduler.shutdown()
        window.close()
        break
    elif event in [server.name for server in serverlist]:
        scheduler.pause()
        update_element([server for server in 
                         serverlist if server.name == event][0])
        scheduler.resume()

Raspberry Pi Pico

I ordered a few Raspberry Pi Picos on its release, and thus far, I am very impressed with this small and inexpensive microcontroller.

The Raspberry Pi Pico sells for $4 (USD) and has the following specifications:
– RP2040 microcontroller chip designed by Raspberry Pi
– Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz
– 264KB on-chip SRAM
– 2MB on-board QSPI Flash
– 26 multifunction GPIO pins, including 3 analogue inputs
– 2 × UART, 2 × SPI controllers, 2 × I2C controllers, 16 × PWM channels
– 1 × USB 1.1 controller and PHY, with host and device support
– 8 × Programmable I/O (PIO) state machines for custom peripheral support
– Low-power sleep and dormant modes
– Accurate on-chip clock
– Temperature sensor
– Accelerated integer and floating-point libraries on-chip

It is a versatile little microcontroller that nicely fills the gap between Arduino and similar microcontrollers and the more traditional Raspberry Pis or similar single board computers.
I have only scratched the surface of using the Pico on some really basic projects, but I have quite a few ideas of using it on some more interesting projects in the future.

3D Printing

I ran into some problems with my 3D printer (Wanhao i3 Mini) over the last few months. The First problem was that half of the printed LCD display died, which was an annoyance, but the printer was still usable. The next issue, which was significantly more severe, was that the printer was unable to heat up the hot end.

My first course of action was to replace both the heating cartridge and the thermistor to ensure that neither of those components were to blame, and unfortunately, they were not. After some diagnostics with a multimeter on the printer’s motherboard, I determined that no power was passing through to the heating cartridge connectors on the motherboard.

I ordered a replacement motherboard and installed it, and the 3D printer is working as good as new again. When I have some more time, I will try and diagnose the exact problem on the old motherboard and repair it.
Here are photos of the old motherboard I removed from the printer:

Below are some photos of a few things I have 3D printed the last few months:

2021 PROJECTS

Pololu Zumo 32U4 Robot

zumo32u4

In a previous post I looked at the Pololu Robot shield for Arduino, which was a robot shield on top of which a Arduino UNO R3 plugged into to form a great little autonomous robot.

Today we will be looking at the Pololu Zumo 32U4 Robot, a robot similar in size to the Zumo Robot shield for Arduino, but with quite a few changes. Firstly it no longer requires a separate Arduino board as it has an Arduino compatible micro-controller directly integrated into its main-board. It also has a LCD screen and IR proximity sensors which the previously mentioned robot did not have.

The Zumo Robot shield for Arduino came with 75:1 HP motors which produce average speed and torque. In the new Zumo I am installing 100:1 HP motors which are slower that the 75:1 HP motors but produce a lot more torque (which will be great for pushing in Robot Sumo matches).

Similarly to the Zumo Robot shield for Arduino the robot also has an expansion area that can be used to connect additional sensors and actuators. As with the Zumo Robot shield for Arduino various different operating source code can be downloaded from Pololu website, that changes the robot into anything from a sumo fighter to a line follower or even an auto-balancing robot, to name a few.

I bought the Zumo 32U4 Robot kit, which required assembly (unlike the Zumo Robot shield for Arduino that only required an Arduino to be plugged in). 

Here is a time Lapse of the robots assembly. 

I really like the Pololu Zumo series of robots and find them reliable, easy to develop for and a great deal of fun. There are various options available, from fully assembled to kit form depending what you are interested in.

zumos

And now that I have two, I can finally have some Robot Sumo fights, so expect some videos of that soon.

Pololu Zumo 32U4 Robot

Elecfreaks Arduino Advanced Kit

Box2

The Elecfreaks Arduino Advanced Kit is an AWSOME product. It contains everything you need to build some impressive Arduino based projects, including a MP3 player, an Alcohol tester and a Tetris game to name a few.

The Kit includes:

  • 1 x Freaduino UNO    
  • 1 x mini USB cable
  • 1 x TFT1.8 LCD 
  • 1 x Octopus ADKey     
  • 1 x Octopus Passive Buzzer Brick    
  • 1 x Octopus MQ3 Gas Sensor Brick     
  • 1 x MP3 Module     
  • 1 x Color Sensor     
  • 1 x 9 DOF Module
  • 1 x ESP8266 Serial Wi-Fi Module
  • 1 x BLE Adapter 
  • 1 x One Channel Relay Brick 
  • 1 x Octopus 5mm LED Brick
  • 1 x 9V AA Battery Holder
  • 30 x Jumper wires

The Kit comes with an Arduino compatible Freaduino board, which is simply an Arduino UNO R3 manufactured by Elecfreaks.

All the components come individually packed in small boxes (all of which are clearly labeled) and it is really well presented.

The kit also includes color printed cards illustrating each project and how to assemble it. Additionally the kit has a wiki page (http://www.elecfreaks.com/wiki/index.php?title=Arduino_Advanced_Kit_-_EN), which contains the source code for all the projects.

The Elecfreaks Arduino Advanced Kit is great value as it is less expensive than buying all the individual components separately (and also a great deal more convenient).

I highly recommend this kit to anyone interested in developing/building in the Arduino space.  

Elecfreaks Arduino Advanced Kit

IoT

I am starting an IoT project and wanted to share a little bit.  IoT or the Internet of Things is defined on Wikipedia as “the network of physical objects—devices, vehicles, buildings and other items embedded with electronics, software, sensors and network connectivity—that enables these objects to collect and exchange data. The Internet of Things allows objects to be sensed and controlled remotely across existing network infrastructure, creating opportunities for more direct integration of the physical world into computer-based systems, and resulting in improved efficiency, accuracy and economic benefit;”.  

To learn more I would recommend the book The Internet of Things Do-It-Yourself at Home Projects for Arduino, Raspberry Pi, and BeagleBone Black by Donald Norris. It provides an in-depth technical overview of concepts as well as some projects that can be built. The projects in the book are not particularly exciting but they do a good job at illustrating concepts and methods utilised.

Book

So I am going to be using a Raspberry Pi2 running Windows 10 IoT core, which will be communicating with some Arduino boards.

I am also looking at integrating with Azure Machine Learning to do some interesting things. 

I have not decided on many elements of the final project, but it will involve a robot.

rasp

On a side note, do not try to deploy Windows 10 IoT Core on a SD card using a Mac, it is a huge pain. My main computer I use at home (and for most of my development, blogging, video editing, etc.) is a MacBook Pro and in the end I gave up trying to get the deploy working and used my windows laptop which worked almost instantaneously.

Once I have decided exactly what I want to achieve and made some progress I will post more on this topic.

IoT

BITE SIZE ARDUINO – PIEZO BUZZER

Today we will have a look at how to connect a piezo buzzer to an Arduino and how to generate different audio signals with it. A piezo buzzer is a audio signalling device, it is the most basic electronic component by which to generate sounds at different frequencies.

A piezo buzzer has 2 connection terminals, one is connected to GND and the other to a PWM digital pin, for this example we will use pin 3.

piezo_bb

We will use the tone() function to generate tones at different frequencies, for an Arduino Uno the frequency rage is between 31 and 65535 Hz. Please note that the possible min and max frequencies differ between different models of Arduino boards. The tone() function takes 3 parameters, firstly the pin to use, then the frequency to use and lastly the duration to generate the tone in milliseconds.

Here is the code used:

#define PIEZO_PIN 3

void setup()
{
}

void loop()
{
     tone(PIEZO_PIN, 31, 1000);
     delay(500); // Pause between Tones 
     tone(PIEZO_PIN, 15000, 1000);
     delay(500); // Pause between Tones 
     tone(PIEZO_PIN, 30000, 1000);
     delay(500); // Pause between Tones 
     tone(PIEZO_PIN, 45000, 1000);
     delay(500); // Pause between Tones 
     tone(PIEZO_PIN, 65535, 1000);
     delay(500); // Pause between Tones 
     noTone(PIEZO_PIN); // Silence Tones
     delay(500);
}
BITE SIZE ARDUINO – PIEZO BUZZER

BITE SIZE ARDUINO – RGB LED

A RGB LED is a LED that can change the colour of the light it produces depending on which of the LEDs’ Connectors have current flowing through them. The LED has 4 connectors, one connector for red, one for green, one for blue and then finally an anode or a cathode, depending if the RGB is a common anode or cathode LED.

So what is the difference between common anode and common cathode?

Well a RGB LED is actually a combination of 3 LEDs, a red LED, a green LED and a blue LED. All LEDs have 2 connectors, an anode and a cathode. So depending how these LEDs are connected together determines if they share an anode or a cathode, thus common anode RGB LED or common cathode RGB LED. The Anode\Cathode leg can be identified as it is the longest leg on the LED. Below are 2 diagrams that illustrates the difference discussed.

Common Cathode:

Common Cathode_schemCommon Anode:

Common Anode_schem

How these 2 different RGB LEDs are connected to a circuit also differs, let us first have a look at a circuit that contains a common cathode RGB LED:

common cathode arduino_bb

Here is the code used with this circuit:

int redPin = 9;
int greenPin = 10;
int bluePin = 11;
 
void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);  
}
 
void loop()
{
  setLEDColour(255, 0, 0);  // red
  delay(2000);
  setLEDColour(0, 255, 0);  // green
  delay(2000);
  setLEDColour(0, 0, 255);  // blue
  delay(2000);
  setLEDColour(255, 255, 0);  // yellow
  delay(2000);  
  setLEDColour(80, 0, 80);  // purple
  delay(2000);
}
 
void setLEDColour(int red, int green, int blue)
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);  
}

Now let us have a look at a circuit that contains a common anode RGB LED:

common anode arduino_bb

Code used with this circuit:

int redPin = 11;
int greenPin = 10;
int bluePin = 9;
 
void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);  
}
 
void loop()
{
  setLEDColour(255, 0, 0);  // red
  delay(2000);
  setLEDColour(0, 255, 0);  // green
  delay(2000);
  setLEDColour(0, 0, 255);  // blue
  delay(2000);
  setLEDColour(255, 255, 0);  // yellow
  delay(2000);  
  setLEDColour(80, 0, 80);  // purple
  delay(2000);
}
 
void setLEDColour(int red, int green, int blue)
{
  red = 255 - red;
  green = 255 - green;
  blue = 255 - blue;

  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);  
}

Although the circuits and code differ between the 2 types of RGB LEDs, the end results are exactly the same.

Try changing the values passed into the setLEDColour function to see what different colours can be created.

BITE SIZE ARDUINO – RGB LED

BITE SIZE ARDUINO – SERVO

Today we will have a look at how to connect a servo motor to an Arduino and how to control its movement.

A servo motor has 3 connector wires:
– A red wire for (+) power.
– A black wire for (-) power (GND).
– A orange, yellow or white cable for signal.

servo_bb

The signal wire of the servo must be connected to one of the analog pins on the Arduino, for the purpose of this example we will use A2. The red wire must be connected to the 5V pin on the Arduino and the black wire to the GND pin on the Arduino. As can be seen in the diagram above – a 100uF capacitor is connected between the 2 power terminals, the reason for this is that it prevents a voltage drop occurring in the circuit when the servo starts moving. A voltage drop can occur due to the fact that a servo consumes more power when starting to move then when it is already moving.

Below is the code used to rotate the servo to different positions:

#include "Servo.h" 

#define SERVO_PIN A2

Servo servoMotor;  

void setup()
{
    servoMotor.attach(SERVO_PIN);
}

void loop()
{
     servoMotor.write(0); // Rotate Servo to 0 Degrees
     delay(500); // Delay to allow Servo time to Move
     servoMotor.write(90); // Rotate Servo to 90 Degrees
     delay(500); // Delay to allow Servo time to Move
     servoMotor.write(180); // Rotate Servo to 180 Degrees
     delay(500); // Delay to allow Servo time to Move
}
BITE SIZE ARDUINO – SERVO

BITE SIZE ARDUINO – 3 PIN SNAP-ACTION LEVER SWITCH

Today we are looking at how to connect a 3 pin snap-action lever switch to an Arduino board and reading when it is pressed.

switch

The lever switch has 3 pins – the common terminal, the normally off terminal and the normally on terminal. If the switch is not pressed current will flow from the common terminal to the normally on terminal, however if the switch is pressed current will cease flowing from common to normally on and will start flowing from the common to normally off terminals.

For this example we will only utilise 2 of the terminals – the common and the normally off terminal.

The common terminal is connected to the 5V pin on the Arduino board and the normally off terminals’ connection is split:

lever Switch_bb

One leg connecting to the Arduino boards’ ground pin with a 10kOhm resistor in series.
The other leg connecting to a digital pin on the Arduino board, for this example digital pin 2.

Here is the code to determine when the switch is pressed:

#define LEVER_SWITCH_PIN 2
int pressSwitch = 0;
void setup()
{
Serial.begin(9600);
}

void loop()
{
pinMode(LEVER_SWITCH_PIN,INPUT);
pressSwitch = digitalRead(LEVER_SWITCH_PIN);
if(pressSwitch == HIGH)
{
Serial.println("Switch Pressed!");
delay(1000);
}
}
BITE SIZE ARDUINO – 3 PIN SNAP-ACTION LEVER SWITCH

Bite Size Arduino – Sharp IR Sensor

I have received a few messages asking me to give a bit more detail into the individual bits of the robots I have built so far. Thus I am starting this series of posts in which I will cover a single sensor\actuator integration to an Arduino board per post.

Today we will have a look at how to use a Sharp IR Sensor.

The IR sensor has 3 pins – 2 pins used to power the sensor and a signal pin that is used to communicate its reading.

sharpIR_bb

As shown in the image above, connect the red pin to the 5V pin on the Arduino, the black to the GND pin and the yellow signal pin to any one of the analog pins, for the purpose of this example we will use A4.

Below is the code used to get a reading from the sensor and print it out using the Serial.println:

#define IR_PIN A4
int IRDist = 0; 

void setup()
{
Serial.begin(9600);
}

void loop()
{
pinMode(IR_PIN,INPUT);
IRDist = analogRead(IR_PIN);
Serial.println(IRDist);
delay(1000);
}

I suggest using this code to experiment and see what readings get generated by placing the sensor at different distances from an obstacle.

Bite Size Arduino – Sharp IR Sensor

Roaming Robot Update

robot1

My Roaming robot has recently been giving me some problems, specifically regarding the power distribution between the 2 motors (with one wheel sporadicly turning faster than the other). I initially thought that one of the motors might have been damaged so I replaced both, only to have the problem remain. After some testing and replacing both the Pololu Dual MC33926 Motor Driver Shield and the Arduino Uno R3, I determined that the problem lay with the Pololu Motor shield. I am not sure if one of the other sensors or actuators was causing some interference on the shield or if it is simply a design flaw in the shield, but I found it impossible to balance the power of the 2 motors. 

I thus decided to replace the Pololu Dual MC33926 Motor Driver Shield with a Pololu DRV8833 Dual Motor Driver Carrier, and this resolved the problem I was experiencing. 

Here the Pololu Dual MC33926 Motor Driver Shield and the Pololu DRV8833 Dual Motor Driver Carrier can be seen side by side (the  Pololu DRV8833 Dual Motor Driver Carrier being the much smaller of the 2): 

motordrivers

I mounted the Motor driver on a bread board, attached on top of an Adafruit Proto-shield. This has the added benefit of having screw terminals for the Arduino pins, so that the jumper cables can no longer accidentally become dislodged.

Proto      protodriver

To install the new DRV8833 Motor Driver I had to switch some of the pin usage on the Arduino in order to free up some PWM digital pins needed by the motor driver. The new Layout is as follows:

Analog Pins:

  • A0 
  • A1 
  • A2 – Servo 
  • A3
  • A4 – IR Sensor
  • A5 – Photo-resistor

Digital Pins:

  • 0
  • 1
  • 2 – LED
  • 3 – Motor Driver B IN 1
  • 5 – Motor Driver B IN 2
  • 6 – Motor Driver A IN 1
  • 7 – Ultrasonic Sensor
  • 8 – Right Trigger Switch
  • 9 – Motor Driver A IN 2
  • 10 
  • 11 – Left Trigger Switch
  • 12 
  • 13

Here are the updated drawings illustrating the wiring of the different components:

robot 1_bb

robot part 2_bb

robot part 3_bb2


I also replaced some of the wiring to the Ultrasonic sensor as they had become worn due to the “neck movement” of the servo pointing the sensor in different directions.

I also ran the power for the Ultrasonic sensor straight from the Arduino and no longer via the Proto-board, this was simply to give the cables a bit more play for the “neck movement” performed by the servo.

After these changes the little guy is working perfectly again.

I will be posting a video of this robot in action in the near future.

Here is the updated code for the robot:


#include "Servo.h" 

#define IR_PIN A4
#define SERVO_PIN A2
#define PING_PIN 7
#define BUMPER_LEFT_PIN 11
#define BUMPER_RIGHT_PIN 8
#define LDR_PIN A5
#define LED_PIN 2
#define IR_DROP 500 //Distance considered a potential drop
#define MIN_LIGHT 300 //Level of light to turn on LED for light
#define BIN_1  3
#define BIN_2  5
#define AIN_1  6
#define AIN_2  9
#define MAX_PWM_VOLTAGE  150

int IRDist = 0; 
int bpLeft = 0; 
int bpRight = 0; 
int LDRValue = 0;
const int dangerThresh = 16;// (in cm) used for obstacle avoidance
int leftDistance, rightDistance; //distances on either side
Servo panMotor; //'neck' servo 
long duration; //time it takes to recieve PING signal

void setup()
{
  Serial.begin(9600); //used for serial communication for debugging 
  pinMode(BUMPER_LEFT_PIN,INPUT);
  pinMode(BUMPER_RIGHT_PIN,INPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BIN_1, OUTPUT);
  pinMode(BIN_2, OUTPUT);
  pinMode(AIN_1, OUTPUT);
  pinMode(AIN_2, OUTPUT);
}

void moveStop()
{
  digitalWrite(BIN_1, LOW);
  digitalWrite(BIN_2, LOW);
  digitalWrite(AIN_1, LOW);
  digitalWrite(AIN_2, LOW);
}

void moveForward()
{
  digitalWrite(BIN_1, LOW);
  analogWrite(BIN_2, MAX_PWM_VOLTAGE);
  analogWrite(AIN_1, MAX_PWM_VOLTAGE);
  digitalWrite(AIN_2, LOW);
  delay(300);
}

void turnLeft()
{
  digitalWrite(BIN_1, LOW);
  analogWrite(BIN_2, MAX_PWM_VOLTAGE);
  digitalWrite(AIN_1, LOW);
  analogWrite(AIN_2, MAX_PWM_VOLTAGE);
  delay(300); 
}

void turnRight()
{
  analogWrite(BIN_1, MAX_PWM_VOLTAGE);
  digitalWrite(BIN_2, LOW);
  analogWrite(AIN_1, MAX_PWM_VOLTAGE);
  digitalWrite(AIN_2, LOW);
  delay(300);
}

void moveBack()
{
   analogWrite(BIN_1, MAX_PWM_VOLTAGE);
   digitalWrite(BIN_2, LOW);
   digitalWrite(AIN_1, LOW);
   analogWrite(AIN_2, MAX_PWM_VOLTAGE);
   delay(500); 
}

int checkDrop()
{
  pinMode(IR_PIN,INPUT);
  IRDist = analogRead(IR_PIN);    
  //Serial.println(IRDist);
  if(IRDist &lt; IR_DROP) 
  { 
    return 1; //Drop present (determined with IR distance sensor)
  }
  else
  {
    return 0;
  }
}

void lightDarkness()
{
 LDRValue = analogRead(LDR_PIN);
 if(LDRValue &lt; MIN_LIGHT)
  {
      digitalWrite(LED_PIN,HIGH); //It is dark, turn on the light
  }
  else
  {
    digitalWrite(LED_PIN,LOW);
  }
}

int checkLeftBumper()
{
  bpLeft = digitalRead(BUMPER_LEFT_PIN);
  if(bpLeft == HIGH)
  {  
    //Serial.println("Left Bumper");
    //HIT!
    return 1;
  }
  else
  {
    return 0;
  }
}

int checkRightBumper()
{
   bpRight = digitalRead(BUMPER_RIGHT_PIN);
  if(bpRight == HIGH)
  {
    //Serial.println("Right Bumper");
    //HIT!
    return 1;
  }
  else
  {
    return 0;
  }
}

void compareDistance()
{
  if (leftDistance&gt;rightDistance) //if left is less obstructed 
  {
    turnLeft();
  }
  else if (rightDistance&gt;leftDistance) //if right is less obstructed
  {
    turnRight();
  }
   else //if they are equally obstructed
  {
    moveBack();
  }
}

long ping()
{
  // Send Ping pulse
  pinMode(PING_PIN, OUTPUT);
  digitalWrite(PING_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_PIN, LOW);
  
  //Get duration it takes to receive echo of Ping sent
  pinMode(PING_PIN, INPUT);
  duration = pulseIn(PING_PIN, HIGH);
  
  //Convert duration into distance (cm)
  return duration / 29 / 2;
}

void loop()
{
  
  lightDarkness();
  if(checkDrop() == 1)
  {
    moveBack();
    moveBack();
    moveBack();
    turnRight();
  }
  else
  if(checkLeftBumper() == 1)
  {
    moveBack();
    turnRight();
  } 
  else if(checkRightBumper() == 1)
  {
    moveBack();
    turnLeft();
  } 
  else
  {
  moveStop();
  int distanceFwd = ping();
  //Serial.println(distanceFwd);
  if (distanceFwd&gt;dangerThresh) //if path is clear
  {
   moveForward();
  }
  else //if path is blocked
  {
    moveStop();
    
    panMotor.attach(SERVO_PIN);
    panMotor.write(20); //look right

    delay(400);
    
    rightDistance = ping(); //scan to the right
    panMotor.write(160); //look left

    delay(550);
    
    leftDistance = ping(); //scan to the left
    panMotor.write(90); //look to center

    delay(400);
    
    panMotor.detach();
    compareDistance();
  }
  }
}
Roaming Robot Update