RaDAR – Arduino controlled robotics

Something I started almost two decades ago but with Arduino’s and modern cheap sensors, my interest has once again been awakened. The knowledge will work it’s way into RaDAR for sure!!!

I’m building a self balancing (Two wheeler) rover robot using scrapped wiper motors I bought around the year 2001. Meet the new Mach 2018 roving robot 🙂

Infrared sensors have been installed at each corner to serve as obstacle avoidance sensors. Specific motor movements have been programmed in the event of an obstacle being detected within a 5cm range. This is the first intelligence the robot will carry on which I will build further. Ultrasonic range sensors will be next, a very effective solution to detect obstacles up to a few meters away which can be accurate up to 5mm!!!

I have installed a tiny screen to display simple diagnostics.

My Arduino code so far for this is as follows:

/*

Mach 2018 – driven by Arduino.

Eddie Leighton – 23rd March 2018

*/

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

// ———————————————————————————-

int RPWM_Output = 5;
int LPWM_Output = 6;

int M2RPWM_Output = 9;
int M2LPWM_Output = 10;

// ———————————————————————————-

int LED = 13; // Use the onboard Uno LED

int RBObstaclePin = 0; // This is our input pin
int RBObstacle = HIGH; // HIGH MEANS NO OBSTACLE

int LBObstaclePin = 1;
int LBObstacle = HIGH;

int LFObstaclePin = 2;
int LFObstacle = HIGH;

int RFObstaclePin = 3;
int RFObstacle = HIGH;

// ———————————————————————————-

void setup()

{

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C

display.clearDisplay();
display.display();

display.setTextColor(WHITE);
display.setTextSize(2);

display.setCursor(10,0);
display.print(“Mach 2018”);
display.display();

// ———————————————————————————–

pinMode(RPWM_Output, OUTPUT);
pinMode(LPWM_Output, OUTPUT);

pinMode(M2RPWM_Output, OUTPUT);
pinMode(M2LPWM_Output, OUTPUT);

// ———————————————————————————–

pinMode(RBObstaclePin, INPUT);
pinMode(LBObstaclePin, INPUT);

pinMode(RFObstaclePin, INPUT);
pinMode(LFObstaclePin, INPUT);

pinMode(LED, OUTPUT);

}

void loop()
{

display.clearDisplay();
display.display();

display.setTextColor(WHITE);
display.setTextSize(2);

display.setCursor(10,0);
display.print(“Mach 2018”);

display.setTextSize(1);

// ———————————————————————————–

RBObstacle = digitalRead(RBObstaclePin);

if (RBObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Right back”);
digitalWrite(LED, HIGH);
display.display();

stopBOT(); // STOP
delay (100); // Motors still

slowFWD(); // Move forward slowly
delay(1000); // for one second

stopBOT();
delay (100);

slowSpinCW (); // Spin slowly clockwise
delay(1000); // for one second

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

// ———————————————————————————–

LBObstacle = digitalRead(LBObstaclePin);

if (LBObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Left back”);
digitalWrite(LED, HIGH);
display.display();

stopBOT();
delay (100);

slowFWD();
delay(1000);

stopBOT();
delay (100);

slowSpinCCW (); // Spin anti-clockwise
delay(1000); // for one second

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

// ———————————————————————————–

LFObstacle = digitalRead(LFObstaclePin);

if (LFObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Left front”);
digitalWrite(LED, HIGH);
display.display();

stopBOT();
delay (100);

slowREV(); // Move backwards slowly
delay(1000); // for one second

stopBOT();
delay (100);

slowSpinCW ();
delay(1000);

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

// ———————————————————————————–

RFObstacle = digitalRead(RFObstaclePin);

if (RFObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Right front”);
digitalWrite(LED, HIGH);
display.display();

stopBOT();
delay (100);

slowREV();
delay(1000);

stopBOT();
delay (100);

slowSpinCCW ();
delay(1000);

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

}

// — Mach motor control for specific movements ————————————-

void slowFWD () {

int reversePWM = -(400 – 511) / 2; // Left motor slow forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = -(400 – 511) / 2; // Right motor slow forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void slowREV () {

int forwardPWM = (600 – 512) / 2; // Left motor slow reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2reversePWM = (600 – 512) / 2; // Right motor slow reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

// ———————————————————————————–

void stopBOT () {

int reversePWM = -(500 – 511) / 2; // Left motor STOP
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = -(500 – 511) / 2; // Right motor STOP
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void fastFWD () {

int reversePWM = -(600 – 511) / 2; // Left motor fast forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = -(600 – 511) / 2; // Right motor fast forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void fastREV () {

int forwardPWM = (400 – 512) / 2; // Left motor fast reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2reversePWM = (400 – 512) / 2; // Right motor fast reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

// ———————————————————————————–

void slowSpinCW () {

int reversePWM = -(400 – 511) / 2; // Left motor slow forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2reversePWM = (600 – 512) / 2; // Right motor slow reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

// ———————————————————————————–

void slowSpinCCW () {

int forwardPWM = (600 – 512) / 2; // Left motor slow reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2forwardPWM = -(400 – 511) / 2; // Right motor slow forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

===========================================================================================

Next test, hoping to send variable speeds to the motors, essential when implementing self balancing!!!

/*

Mach 2018 – driven by Arduino.

Eddie Leighton – 23rd March 2018

*/

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

// ———————————————————————————-

int RPWM_Output = 5;
int LPWM_Output = 6;

int M2RPWM_Output = 9;
int M2LPWM_Output = 10;

// ———————————————————————————-

int LED = 13; // Use the onboard Uno LED

int RBObstaclePin = 0; // This is our input pin
int RBObstacle = HIGH; // HIGH MEANS NO OBSTACLE

int LBObstaclePin = 1;
int LBObstacle = HIGH;

int LFObstaclePin = 2;
int LFObstacle = HIGH;

int RFObstaclePin = 3;
int RFObstacle = HIGH;

// ———————————————————————————-

void setup()

{

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C

display.clearDisplay();
display.display();

display.setTextColor(WHITE);
display.setTextSize(2);

display.setCursor(10,0);
display.print(“Mach 2018”);
display.display();

// ———————————————————————————–

pinMode(RPWM_Output, OUTPUT);
pinMode(LPWM_Output, OUTPUT);

pinMode(M2RPWM_Output, OUTPUT);
pinMode(M2LPWM_Output, OUTPUT);

// ———————————————————————————–

pinMode(RBObstaclePin, INPUT);
pinMode(LBObstaclePin, INPUT);

pinMode(RFObstaclePin, INPUT);
pinMode(LFObstaclePin, INPUT);

pinMode(LED, OUTPUT);

}

void loop()
{

display.clearDisplay();
display.display();

display.setTextColor(WHITE);
display.setTextSize(2);

display.setCursor(10,0);
display.print(“Mach 2018”);

display.setTextSize(1);

// — Slow to fast, forward ———————————————————

for (int i=50; i >= -50; i–){

FWD(i);

delay(10);

}

stopBOT();
delay (100);

// — Slow to fast, reverse ———————————————————

for (int i=50; i >= -50; i–){

REV(i);

delay(10);

}

stopBOT();
delay (100);

// ———————————————————————————–

RBObstacle = digitalRead(RBObstaclePin);

if (RBObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Right back”);
digitalWrite(LED, HIGH);
display.display();

stopBOT(); // STOP
delay (100); // Motors still

slowFWD(); // Move forward slowly
delay(1000); // for one second

stopBOT();
delay (100);

slowSpinCW (); // Spin slowly clockwise
delay(1000); // for one second

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

// ———————————————————————————–

LBObstacle = digitalRead(LBObstaclePin);

if (LBObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Left back”);
digitalWrite(LED, HIGH);
display.display();

stopBOT();
delay (100);

slowFWD();
delay(1000);

stopBOT();
delay (100);

slowSpinCCW (); // Spin anti-clockwise
delay(1000); // for one second

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

// ———————————————————————————–

LFObstacle = digitalRead(LFObstaclePin);

if (LFObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Left front”);
digitalWrite(LED, HIGH);
display.display();

stopBOT();
delay (100);

slowREV(); // Move backwards slowly
delay(1000); // for one second

stopBOT();
delay (100);

slowSpinCW ();
delay(1000);

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

// ———————————————————————————–

RFObstacle = digitalRead(RFObstaclePin);

if (RFObstacle == LOW)
{

display.setCursor(10,40);
display.print(“Right front”);
digitalWrite(LED, HIGH);
display.display();

stopBOT();
delay (100);

slowREV();
delay(1000);

stopBOT();
delay (100);

slowSpinCCW ();
delay(1000);

stopBOT();
delay (100);

display.clearDisplay();
display.display();

}

}

// — Mach motor control for specific movements ————————————-

void slowFWD () {

int reversePWM = -(400 – 511) / 2; // Left motor slow forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = -(400 – 511) / 2; // Right motor slow forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void slowREV () {

int forwardPWM = (600 – 512) / 2; // Left motor slow reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2reversePWM = (600 – 512) / 2; // Right motor slow reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

// ———————————————————————————–

void stopBOT () {

int reversePWM = -(500 – 511) / 2; // Left motor STOP
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = -(500 – 511) / 2; // Right motor STOP
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void fastFWD () {

int reversePWM = -(600 – 511) / 2; // Left motor fast forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = -(600 – 511) / 2; // Right motor fast forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void fastREV () {

int forwardPWM = (400 – 512) / 2; // Left motor fast reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2reversePWM = (400 – 512) / 2; // Right motor fast reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

// ———————————————————————————–

void slowSpinCW () {

int reversePWM = -(400 – 511) / 2; // Left motor slow forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2reversePWM = (600 – 512) / 2; // Right motor slow reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

// ———————————————————————————–

void slowSpinCCW () {

int forwardPWM = (600 – 512) / 2; // Left motor slow reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2forwardPWM = -(400 – 511) / 2; // Right motor slow forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void FWD (int spoed) {

// Slow 50 ….. to …… fast -50

int reversePWM = spoed; // Left motor forward
analogWrite(LPWM_Output, 0);
analogWrite(RPWM_Output, reversePWM);

int M2forwardPWM = spoed; // Right motor forward
analogWrite(M2LPWM_Output, M2forwardPWM);
analogWrite(M2RPWM_Output, 0);

}

// ———————————————————————————–

void REV (int spoed) {

// Slow 50 ….. to …… fast -50

int forwardPWM = spoed; // Left motor reverse
analogWrite(LPWM_Output, forwardPWM);
analogWrite(RPWM_Output, 0);

int M2reversePWM = spoed; // Right motor reverse
analogWrite(M2LPWM_Output, 0);
analogWrite(M2RPWM_Output, M2reversePWM);

}

RaDAR – The new ZS6BKW Maak Toe field measurements

I took part in the local 40m Hamnet contest this weekend using my FT817ND and 9:1 UNUN fed long wire hanging over a high tree branch. My deployment point was close to where I have hung the new ZS6BKW antenna (“Maak toe”), published in the March 2018 Radcom magazine by Brian Austin G0GSF, high up in the trees. I worked two SOTA stations during the exercise.

Propagation wasn’t the best so I spent some “Off time” taking some measurements on the BKW using the 817’s SWR indicator to determine “SWR”. I drew up the following chart as an indication of what the values looked like graphically. Note no tuner was in line.

The green values are for 40m and on the lower part of the band no SWR could be seen but started to lift halfway up the band at 7.1 MHz so the antenna is resonating low on the 40m band. Ideal for CW, Digital modes and SSB.

The brown values are for 10m and a dip in SWR can be clearly seen starting from 28.4 MHz where no SWR could be seen for at least 300 kHz and where the SWR started to slowly climb around 28.8 MHz. At 29.3 MHz the SWR indicator showed 5 bars. The antenna is resonating nicely on the SSB portion of the 10m band. A tuner will be needed for the CW and Digital modes portion of the band.

The yellow values are for 20m and best, but not low, in the CW portion of the band. A SWR indication of 1 bar is really not that critical but the antenna seems to be resonating below the 20m band.

The cyan values are for 17m and the SWR was hovering around 2 to 3 points which would definitely indicate the need for an ATU. The 12m band even more so!

All in all the antenna, in general, is resonating low and may need further trimming of the open wire feeder. I have already removed around a meter but the length is totally reliant on the open wire feed line’s velocity factor (VF).

This antenna was not designed for, and DOES NOT work on 30m and 15m.

The antenna lives in the trees ….. in KG34ac.

73 de Eddie ZS6BNE

RaDAR – Smartphones

Quite a few years ago in the early days of Android I invested in a top of the range Samsung Galaxy Note (It came at the price of a FT817), one of the first “Note” phones. It was my way of getting to know this popular operating system in my job as technology manager. I discovered HamGPS an app capable of using the phones GPS to determine a 10 character maidenhead grid. This immediately became part of RaDAR.

It was in the days where I had no cell phone contract and used the method, “Pay as you go” on the MTN network. I worked this way from way back when I had a Nokia 3310 and even before that, a NEC! Then while on “early retirement” my XYL convinced me to take out a cell phone contract with cell c – it was the biggest mistake of my life! The phone they gave me was a Sony C4 which really had an excellent camera for photos and videos but that was about all. I constantly lost signal and the touch screen became a disaster half way through the contract and could not be replaced. On Friday I terminated the two year contract in it’s final month so by this time next month I will be contract free – and free!

In the meantime I’m using my XYL’s old Sony and have given my old “Note” to Eduan, my grandson. So that leaves me without the capability of determining 10 character maidenhead grids as the Sony I have now doesn’t have a built in GPS!

Maybe this is a good thing that I get back to using my very old Garmin Legend handheld GPS last used with APRS, even via FM satellites!

I can now only determine a 6 character grid square …… but, let’s see how it goes.