Bite Size Arduino – Analog vs Digital Pins

I will use the Arduino Bite Size posts to share small bits of information relating to the Arduino platform.

Today we will be examining the 2 main pin types that are present on Arduino boards. For this article I will be referring to the Arduino UNO R3, however all Arduino boards contain these pin types, just note that the quantities of the different pins do vary greatly between the different boards.

There are 2 main groups of pins on any Arduino Board, Analog and Digital pins.

Arduino copy

On this image the Digital pins are highlighted with a red block and the Analog pins with a yellow block.

So what is the difference between the 2 pin types?

Digital pins can read or write 2 possible values HIGH or LOW (1 or 0), whereas Analog pins can read a value between 0 to 1023 and write a value between 0 to 255.

Keeping this in mind it becomes apparent that the main purpose of these pins differ greatly. A Digital PIN can turn an LED on or off, whereas an Analog pin can turn the same LED on to a variety of brightness levels, not just 1. So if you want to simply turn an LED on and off a Digital pin would be the correct pin to use, but for a servo motor signal cable (that controls the movement of a servo motor) an Analog pin would be required as different values (0 to 255) determines how far the servo turns.

This logic also applies when it comes to sensors, for a switch that has 2 states (on and off) a Digital pin would be ideal, however for a IR range sensor it would not work as usually you would like to know a value that represents the distance the sensor is detecting. For this kind of sensor an Analog pin should be used.

So far this all seems pretty straight forward… Now let us consider that some Digital pins can “act” like Analog pins.

You will see by looking at the image on the Arduino above that certain of the Digital pins have ~ next to them. This indicates that the pin is capable of PWM or Pulse Width Modulation. PWM is a method of producing Analog results utilising a Digital means. This is achieved by the Digital pin switching between on and off at a high frequency and thus producing a square wave, where the time in the on state determines the width of the pulses created.

So what does this mean?

If analogWrite(255) is done to a PWM pin it will be in a permanent HIGH (On) state. Whereas analogWrite(0) would place the pin in a permanent LOW (Off) state.

So if analogWrite(127) is done to a PWM pin it will be in a HIGH (On) state roughly 50% of the time and LOW (Off) state for the remaining 50% of the time.  The Arduino PWM frequency is 980Hz, which means that the pin will switch between on and off (HIGH and LOW) approximately every 0.00051 seconds for the 50/50 example above.

Note however that although analogWrite works with PWM pins, analogRead does not. To read a PWM signal the pulseIn method should be used. We will cover the pulseIn method at a later time.

Bite Size Arduino – Analog vs Digital Pins

Bite Size C# – CSV File Creator

Today we will be looking at my CSV Creator class, which is included in my Core.dll library.

It has 1 static method that takes a generic list of objects and a CSV file name. It uses the generic list of objects to construct the CSV file. The properties of the object type contained in the list are used in the creation of the header row of the file. The CSV file name parameter is used to save the created file to disk.

This class in contained in my Core.CSV namespace. Here is the code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Core.CSV
{
    public static class CsvCreator
    {
        public static void CreateCsvFromGenericList<T>(List<T> list, string csvNameWithExt)
        {
            if (list == null || list.Count == 0) return;

            //get type of objects in list
            Type t = list[0].GetType();
            string newLine = Environment.NewLine;

            using (var sw = new StreamWriter(csvNameWithExt))
            {
                //Create an instance of the class
                object o = Activator.CreateInstance(t);
                //Get all properties from class created, this will be used for CSV header row
                PropertyInfo[] props = o.GetType().GetProperties();

                //Create header row based on properties of class
                foreach (
                    PropertyInfo prop in
                        props.Where(prop => prop.Name.ToUpper() != "ENTITYSTATE" 
                        && prop.Name.ToUpper() != "ENTITYKEY"))
                {
                    sw.Write(prop.Name.ToUpper() + ",");
                }
                sw.Write(newLine);

                //create data rows using each object in list
                foreach (T item in list)
                {
                    foreach (string rowData in from pi in props
                                               where !Convert.ToString(item.GetType()
                                                        .GetProperty(pi.Name)
                                                        .GetValue(item, null)).Contains("Unchanged") &&
                                                     !Convert.ToString(item.GetType().GetProperty(pi.Name)
                                                                           .GetValue(item, null))
                                                             .Contains("System.Data.EntityKey")
                                               select Convert.ToString(item.GetType()
                                                                           .GetProperty(pi.Name)
                                                                           .GetValue(item, null))
                                                             .Replace(',', ' ') + ',')
                    {
                        sw.Write(rowData);
                    }
                    sw.Write(newLine);
                }
            }
        }
    }
}

This class is useful when you simply want to create a CSV file from a generic object list quickly.

Bite Size C# – CSV File Creator

Gates, Build Gates not Bill Gates

The basis of building any logic circuit (even one as complex as a computer) comes down to logic gates. I will be discussing the 2 most basic logic gates today, an AND gate and an OR gate.

Logic gates are physical circuits that implements boolean functions, so to start let us look at the boolean AND and OR functions.

For all the examples below let us assume that we have 2 inputs: A and B, and that A and B both have 2 possible states: on or off, 1 or 0 in binary terms.

AND Function

An AND function requires both A and B to be in an “on” state to give a positive “on” result. (Just note the NAND function will give a positive “on” output when A and B are NOT both “on”. We will look at the NAND function and gate in detail at a later time).

Below is the state table for the AND function with inputs A and B as well as the resulting output: 

A B Output
0 (off) 0 (off) 0 (off)
1 (on) 0 (off) 0 (off)
0 (off) 1 (on) 0 (off)
1 (on) 1 (on) 1 (on)

OR Function

An OR function requires either A or B  (or both) to be in an “on” state to give a positive “on” result. (Just note the NOR function requires neither A or B to be in an “on” state to give a positive “on” result. Additionally the XOR function will give a positive “on” output only when A or B are “on” but NOT when both are “on”. We will also look at the NOR and XOR functions and gates in detail at a later time).

Below is the state table for the OR function with inputs A and B as well as the resulting output: 

A B Output
0 (off) 0 (off) 0 (off)
1 (on) 0 (off) 1 (on)
0 (off) 1 (on) 1 (on)
1 (on) 1 (on) 1 (on)

Now let us examine the gate circuits. (I have constructed both gates on a Adafruit Perma-Proto board shown in the picture below).

Gates

AND Gate:

Parts required:

  • 3  resistors (10k Ohm will do)
  • 2 push buttons (input A and B)
  • 2 BJT NPN transistors
  • 1 LED (output)

And Gate_bb

AND GATE

AND Gate Schematic

So by pushing the buttons in accordance to the AND state table above the outputs can be recreated. Because the 2 transistors are placed in series the circuit can only be completed when both button A and B are pressed, and thus the AND function is implemented.

OR Gate:

Parts required:

  • 3  resistors (1 x 10k Ohm and 2 x 660 Ohm resistors will do)
  • 2 push buttons (input A and B)
  • 2 BJT NPN transistors
  • 1 LED (output)

Or Gate_bb

OR Gate

OR Gate Schematic

So by pushing the buttons in accordance to the OR state table the corresponding outputs can be recreated. Because the 2 transistors are placed in parallel the circuit can be completed by pressing either the A or B button (or both). The circuit thus represents the OR function.

Just note the selection of resistor sizes are not cast in concrete, just pick a resistance high enough so your transistor does not get fried based on your power supply size (in my case a 9 Volt battery). I simply chose the resistors based on what I had available at the time.

Additionally if the role of the transistors in the circuit does not make sense to you please look at my earlier post (TRANSISTOR CRASH COURSE) that explains the functioning of transistors and their roles in circuits.

Gates, Build Gates not Bill Gates

Bite Size C#

As a software developer I believe it is critical to build reusable code when possible. All software engineers have their toolbox of previously written code that they reuse when the need arises. Keeping this in mind I have built a Class Library, that I continually extend, that contains all the reusable functions that I use across multiple projects. I call this my Core.dll and include it in all the projects I work on.

The project contains multiple classes for a variety of functions, anything from string manipulation to file generation. I will be sharing little code bits from this Core library in the Bite Size C# posts.

Today we will look at my StringExtensions class, which falls in my Core.Extensions namespace.

using System;

namespace Core.Extension
{
    public static class StringExtensions
    {
        public static bool Contains(this string source, string toCheck, StringComparison comp)
        {      
            return source.IndexOf(toCheck, comp) >= 0;
        }

        public static string GetLast(this string source, int tailLength)
        {
            return tailLength >= source.Length ? source : source.Substring(source.Length - tailLength);
        }
    }
}

The Class contains 2 methods:

A Contains function that is similar to the built-in string.Contains method except that it takes a StringComparison parameter so that case sensitivity, culture and sort rules can be configured.

A GetLast method that passes back the requested last bit of a string (for example last 4 characters of a string.)

When this class is included in a project the following operations can be performed:

 private static void Main(string[] args)
        {
            string testString = "This is a test string";
            bool test = testString.Contains("STRING", StringComparison.InvariantCultureIgnoreCase);
                //This will return true as ignore case is set


            string resultString = -testString.GetLast(6);
                //This will return "string", the last 6 characters in the string
        }

This class acts as an extension class to the predefined C# string class, so its methods appear in the class method list exactly like the built-in string method do (such as string.Equals or string.Trim).

Bite Size C#

Roaming Robot

Robot4

Today we will take a detailed look at my Roaming Robot.

Part List:

  • Sparkfun Magician Chassis (this includes 2 DC motors)
  • 1 x Capacitors 100uF
  • 4 x Resistors 220 Ohm
  • 1 x Micro Servo
  • Seeed Ultrasonic Sensor
  • Sharp IR Sensor
  • 2 x Long Arm Trigger Switches
  • 1 x LED (ultra bright white)
  • 1 x Photo-resistor
  • 1 x Arduino Uno R3 
  • 1 x Pololu Dual MC33926 Motor Driver Shield

Power supply:

  • 1 x 9V Battery (used to power the 2 DC motors through the motor shield)
  • 4 x AA Batteries in a battery holder (used to power Arduino and PCB\Breadboard)

The Pololu Dual MC33926 Motor Driver Shield plugs into the Arduino female headers and all connectors shown in below diagrams actually plug into the Motor shield and not directly into the Arduino as shown.

Arduino  ArduinoArduino

The first diagram shows the wiring for the LED, photo-resistor, trigger switches, and the servo:

robot part 1_bb

The two switches shown are actually the 2 long arm trigger switches.

switch

The circuit shown above is very straightforward. However note the capacitor across the servo power terminals. This is to prevent a voltage drop in the circuit caused by the servo starting to move, which draws more current to start moving than when it is already moving.

The below diagram shows how the Seeed Ultrasonic and Sharp IR sensors are wired:

robot part 2_bb

So the Arduino is wired as follows (through the motor driver female headers):

Analog Pins:

  • A0 – this pin is used by the MC33926 Motor shield
  • A1 – this pin is used by the MC33926 Motor shield
  • A2 – Servo 
  • A3
  • A4 – IR Sensor
  • A5 – Photo-resistor

Digital Pins:

  • 0
  • 1
  • 2
  • 3 – LED
  • 4 – this pin is used by the MC33926 Motor shield
  • 5 – Ultrasonic Sensor
  • 6 – Right Trigger Switch
  • 7 – this pin is used by the MC33926 Motor shield
  • 8 – this pin is used by the MC33926 Motor shield
  • 9 – this pin is used by the MC33926 Motor shield
  • 10 – this pin is used by the MC33926 Motor shield
  • 11 – Left Trigger Switch
  • 12 – this pin is used by the MC33926 Motor shield
  • 13

The Arduino VDD (5V) and GND pins are used to power the PCB\Breadboard.

robot4 robot1robot2

The Servo acts as the robots’ neck, it can turn the Ultrasonic Sensor in various directions. The Ultrasonic Sensor is used to detect obstructions, which the robot will then avoid, for obstructions too low for the Ultrasonic Sensor to detect the trigger switches will be pressed and the object can then be avoided. The Photo-resistor is used to detect light level and if it is deemed too dark the LED will turn on. The IR sensor is used to detect drops, so that the robot does not fall down a vertical drop, such as a step.

The two DC motors of the Magician Chassis are connected to the Motor shield, the left motor to the two most left screw terminals on the shield and the right motor to the two most right screw terminals on the shield. The 2 middle screw terminals on the shield are used to power the motors; the 9V battery should be connected to them. (Just note that if one or both of the robots’ motors move in the opposite direction than expected, this can be rectified by switching the 2 motor wires around between the screw terminals they are connected to on the motor shield.)

Here is the code used with the Robot (it is written in C and must be deployed on the Arduino):

#include "DualMC33926MotorShield.h"
#include "Servo.h"

#define IR_PIN A4
#define SERVO_PIN A2
#define PING_PIN 5
#define BUMPER_LEFT_PIN 11
#define BUMPER_RIGHT_PIN 6
#define LDR_PIN A5
#define LED_PIN 3
#define IR_DROP 450 //Distance considered a potential drop
#define MIN_LIGHT 300 //Level of light to turn on LED for light

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

void setup()
{
pinMode(BUMPER_LEFT_PIN,INPUT);
pinMode(BUMPER_RIGHT_PIN,INPUT);
pinMode(LED_PIN, OUTPUT);
}

void moveStop()
{
md.init();
md.setSpeeds(0,0);
}

void moveForward()
{
md.init();
moveStop();
md.setSpeeds(M1Speed,M2Speed);
delay(250);
}

void turnLeft()
{
md.init();
moveStop();
md.setSpeeds(M1Speed,-M2Speed);
delay(250);
}

void turnRight()
{
md.init();
moveStop();
md.setSpeeds(-M1Speed,M2Speed);
delay(250);
}

void moveBack()
{
md.init();
moveStop();
md.setSpeeds(-M1Speed,-M2Speed);
delay(250);
}

int checkDrop()
{
pinMode(IR_PIN,INPUT);
IRDist = analogRead(IR_PIN);
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)
{
//HIT!
return 1;
}
else
{
return 0;
}
}

int checkRightBumper()
{
bpRight = digitalRead(BUMPER_RIGHT_PIN);
if(bpRight == HIGH)
{
//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();
compareDistance();
}
else
if(checkLeftBumper() == 1)
{
moveBack();
compareDistance();
}
else if(checkRightBumper() == 1)
{
moveBack();
compareDistance();
}
else
{
moveStop();
int distanceFwd = ping();

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(250);

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

delay(600);

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

delay(300);

panMotor.detach();
compareDistance();
}
}
}
Roaming Robot