Arduino Tape Measure with OLED Display

The Sketch can be downloaded from my GitHub page here.

Ultrasonic1

This project uses an HC-SR04 Ultrasonic Transmitter/Receiver to measure a distance up to about 100 cm or 3 feet. The result is displayed on a small OLED Display.

The sketch includes a fairly common routine to measure distance in centimeters which is then displayed on a 128 x 64 OLED display. The distance to the object is printed on the Serial Monitor in both Centimeters and inches. A Bar graphic at the bottom of the screen displays the distance, and this is divided by 10cm tick marks.

Ultrasonic2

To even the readings out, five readings are taken and the average calculated and this helps keep the display reasonably steady. I use the U8Glib and this can be downloaded from Google Code here. The connections for the OLED display and the HC_SR04 Ultrasonic unit are shown in the sketch. The SSD1306_128X64 OLED is an I2C device and it is important to connect the power supply correctly as the display will not survive  a polarity reverse.

/***********************************************************
*
* Arduino Tape Measure with OLED Display
*
* By Chris Rouse Nov 2015
*
* HC-SRO4 Connections:
* VCC connection of the sensor attached to +5V
* GND connection of the sensor attached to ground
* TRIG connection of the sensor attached to digital pin 2
* ECHO connection of the sensor attached to digital pin 3
*
* OLED Connections:
* VCC +5v
* GND GND
* SDA Analog pin 4
* SCL Analog pin 5
*
*
********************************************************/

#include "U8glib.h"
#include <SPI.h>
#include <Wire.h>
// setup u8g object
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C
//
const int trigPin = 2;
const int echoPin = 3;
long duration, inches, cm, avgCm;
String longString="";
int tapeLength = 0;

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

void loop() {
avgCm = 0;
for(int f = 0; f <5; f++){ // average out 5 readings
ultrasonic();
avgCm = avgCm + cm;
}
cm = avgCm/5;
//draw loop
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
delay(50);
}

void ultrasonic()
{
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
}
long microsecondsToInches(long microseconds)
{
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds)
{
return microseconds / 29 / 2;
}
void draw(void){
u8g.setFont(u8g_font_profont12);
u8g.drawStr(5,8, "Arduino Tape Measure");
if(cm > 110){
longString = "---";
tapeLength = 0;
}
else{
longString=String(cm)+ "cm";
tapeLength = cm;
}
const char* newData = (const char*) longString.c_str();
u8g.setFont(u8g_font_profont29);
u8g.drawStr(30,40, newData);
// now draw tape
for(int f = 10;f <120; f = f+10){
u8g.drawLine(f,48,f,61);
}
for(int f = 2; f< tapeLength+3; f++){
u8g.drawBox(f,50,1,10);
}
}

Arduino and RFID using UID to identify a Key Master card.

RFID

The Sketch and Library can be downloaded from my GitHub page here.

There is a very good Library for RFID boards using the MFRC522 written by Miguel Balboa. The sketches in the examples show how to connect the RFID board to an Arduino, as the device is powered by 3.3 volts I assumed that the data lines should be 3.3 volts and used bi directional level converters like these here. These converters have four channels and as there are five data lines I used two of them.

The examples show how to read and write data to an RFID tag or card, but I just wanted to use the card like a key, the sketch could hold a list of UIDs that would identify a valid key and could open a lock, or open a specific web site in a browser. The sketch shown here was just a simple test of the idea. A Red and green LED are connected to two of the Arduino Digital pins, the Red led is normally ON and the Green LED is normally OFF. If a valid key is brought near the card reader the Green LED will switch ON for 1 second.

Rather than keep hard coding the UID into the Sketch I included a learning mode. If Digital Pin 4 is connected to Ground, when the sketch is first run the first card read will become the Master Key and will remain so until the Sketch is re-run.

This sketch was really written to test out the idea of using RFID tags as keys and can easily be modified and expanded. All the connections are shown in the sketch. The UID of the card is printed out in the Serial Monitor as both HEX and as a decimal number, the decimal number is a String and is used to compare the card read with the Master value stored in the sketch.
/*
* Identify an RFID tag or card from its UID

* This sketch when first run will store the UID of the first card scanned
* if Digital Pin 4 is connected to Gnd.
* When this card is scanned again the Green LED will light
* All other cards will turn both LEDs off.
* After 1 second the Green LED will be off and the Red LED will be on.
*
* Stored UIDs are lost if the power is removed or the Sketch is reset
*
* Connect a flying lead to pin 4, if the learn Mode is required then
* connect this to Gnd.
*
* UIDs are printed out in HEX and Decimal in the Serial Monitor
*
* Pin layout should be as follows:
* (Bi Directional Logic Level Convertors are required as the device is 3.3volts
* and two are required for the 5 signal lines)
* Signal Pin Pin
* Arduino Uno                 MFRC522 board
* -----------------------------------------
* Reset 5                     RST
* SPI SS 10                   SDA
* SPI MOSI 11                 MOSI
* SPI MISO 12                 MISO
* SPI SCK 13                  SCK
*
* Connect a Red LED in series with a 330R resistor between pin 2 and Gnd
* Connect a Green LED in series with a 330R resistor between pin 3 and Gnd
* Connect Digital Pin 4 to Gnd to activate the Learn Mode
*/
#include
#include

#define SS_PIN 10
#define RST_PIN 5
#define redLed 2
#define greenLed 3
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
String UIDstring;
boolean learnMode = false; // dont ask to remember this card number
String knownCard = "";

void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(4, INPUT_PULLUP);
pinMode(redLed, OUTPUT);
pinMode(greenLed, OUTPUT);
digitalWrite(redLed, HIGH);
digitalWrite(greenLed, LOW);
if(digitalRead(4) == 0){
learnMode = true;
Serial.println("Learn Mode ON");
}
else{
learnMode = false;
Serial.println("Learn Mode OFF");
}
}

void loop() {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}

// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}

// Dump debug info about the card. PICC_HaltA() is automatically called.
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

// Dump UID
Serial.print("Card UID:");
UIDstring = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
UIDstring = UIDstring + String(mfrc522.uid.uidByte[i]);
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
if(learnMode){
knownCard = UIDstring;
learnMode = false; // turn it off
}
Serial.println(UIDstring);
// light correct LED
if (UIDstring == knownCard){
digitalWrite(redLed, LOW);
digitalWrite(greenLed, HIGH);
}
else{
digitalWrite(redLed, LOW); // turn both LEDS off, its the wrong card
digitalWrite(greenLed, LOW);
}
delay(1000);
digitalWrite(redLed, HIGH);
digitalWrite(greenLed, LOW);
}

Using up to 5 Capacitance switches to control up to 5 Relays.

cap_switch_with_relays

The code is available on my GitHub page here.

This project allows up to 5 Capacitance Switches to control up to 5 relays. When a switch is first touched the associated relay closes. When that switch is touched again the relay opens. All relays can be on at the same time and can be switched off in any order.

When the Capacitance switch is touched the output goes LOW, the switch outputs are scanned and as soon as one goes LOW the associated relay is switched on. The sketch then waits for the switch to be released before scanning the switches again. A second touch on the switch will switch the relay off.

There is some attempt to ignore two switches being touched at the same time and the lowest number switch will be accepted. The switch pads are small and close together and my fingers are large so trying to press switch 2 often turns on both switch 1 and switch 2. I suspect the best action for large fingers is to use one of those conductive pens used on smart phones and tablets, but I have not tried that yet.

All five INPUTS are pulled HIGH in the sketch, so they can be left open if only one or two switches are required. In my setup shown above I only have a 4 switch board, so the fifth input is left unconnected.

circuit for 5 cap switch
/*********************************************************

Up to 5 Relays operated by up to 5 capacitance switches

Chris Rouse Nov. 2015

The Capcitance switches are mounted on a small board
connections, G (Gnd) V (Vcc) and Out ( the switch outputs)
The switch outputs go LOW when pressed

Connect Gnd to Arduino Gnd
Connect Vcc to Arduino 5 volts
Connect Outputs to Arduino pins 7 to 12

The relays are switched on by a LOW signal

Connect the Relay board to Gnd and 5 volts
and the control pins to Arduino pins 2 to 6
*********************************************************/

int relay;
int capSwitch;
boolean relay1 = false;
boolean relay2 = false;
boolean relay3 = false;
boolean relay4 = false;
boolean relay5 = false;
boolean pressButton;

# define LED 13 // onboard LED

void setup() {
Serial.begin(9600); // used for debugging
// setup relay switching outputs
for (relay = 1; relay<6; relay++){
pinMode(relay, OUTPUT);
digitalWrite(relay,LOW); // turn OFF the relay
}
//setup capacitance switch inputs
for(capSwitch = 7; capSwitch< 11; capSwitch++){
pinMode(capSwitch, INPUT_PULLUP); // pull any unused inputs HIGH
}
//
// setup onboard LED
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW); // turn LED off
//
Serial.println("This sketch will control upto 5 relays from a bank of upto 5 capacitanc e switches");
Serial.println("At the start all relays should be switched off");
Serial.println("Touching a switch will latch the relay ON, touching that switch again will turn the relay OFF");
}

void loop() {
// turn switch ON on first touch
// OFF on second press
delay(200); // helps stop false triggering
pressButton = false;
relay = 0;
for(capSwitch =7; capSwitch < 11; capSwitch++){
if(pressButton == false){
if ((digitalRead(capSwitch) == HIGH)) {
digitalWrite(LED, HIGH); // turn LED ON to show button press
relay = capSwitch-5; // the pin the relay is connected to
pressButton = true;
// now toggle relay state
switch(relay){
case 2:
if (relay1){digitalWrite(relay, LOW);relay1 = false; Serial.println("Relay 1 OFF");} // relay ON
else{digitalWrite(relay, HIGH);relay1 = true; Serial.println("Relay 1 ON");} // relay OFF
break;

case 3:
if (relay2 == true){digitalWrite(relay, LOW);relay2 = false; Serial.println("Relay 2 OFF");} // relay ON
else{digitalWrite(relay, HIGH);relay2 = true; Serial.println("Relay 2 ON");} // relay OFF
break;
case 4:
if (relay3 == true){digitalWrite(relay, LOW);relay3 = false; Serial.println("Relay 3 OFF");} // relay ON
else{digitalWrite(relay, HIGH);relay3 = true; Serial.println("Relay 3 ON");} // relay OFF
break;
case 5:
if (relay4 == true){digitalWrite(relay, LOW);relay4 = false; Serial.println("Relay 4 OFF");} // relay ON
else{digitalWrite(relay, HIGH);relay4 = true; Serial.println("Relay 4 ON");} // relay OFF
break;
case 6:
if (relay5 == true){digitalWrite(relay, LOW);relay5 = false; Serial.println("Relay 5 OFF");} // relay ON
else{digitalWrite(relay, HIGH);relay5 = true; Serial.println("Relay 5 ON");} // relay OFF
break;

}
// wait here until the cap switch is no longer touched
while (digitalRead(capSwitch) == HIGH){
// wait for switch to be released
}
digitalWrite(LED, LOW); // turn LED OFF as button now released
}
}
}
}

MAX7219 and 8 x 7 Segment LED Display

 

The code for this can be downloaded from my GitHub page here.

This display can be found on eBay here. It consists of two 4 digit seven segment LEDS with a MAX7219 driver IC. I have used the LedControl library available from here, the examples show the basic library use, but I wanted to be able to send data over a Serial connection. The MAX7219 presents some problems in sending a string of characters, unlike some other drivers like the TM1638 where a string can be sent, the MAX7219 needs to set each LED individually.

The sketch below allows a number up to 8 characters (or 7 with a minus sign) to be sent to the Serial port. It can be typed into the Serial Monitor, or sent from, say, a Bluetooth receiver. Characters are received one at a time and stored in an array, once all the data has been received the contents of the array are then sent to the relevant LEDs. The number is also available in the string stringNumber once all characters have been received.

The sketch shows the connections for the board to Arduino, five in total are needed, 5 volts, Ground, Data In is connected Arduino pin 12, CLK is connected to Arduino pin 11 and Load OS connected to Arduino pin 10.

Upload the sketch and switch to the Serial Monitor, select 9600 Baud and NL/CR. Type a number and it will appear on the LEDs, to clear and blank the display send a letter.

/***********************************************************
 * 
 * MAX7219 and 8x7 Segment LED Display
 * 
 * by Chris Rouse November 2015
 * 
 Connections
 pin 12 is connected to the DataIn 
 pin 11 is connected to the CLK 
 pin 10 is connected to LOAD 
 We have a single MAX7219. 
 * 
 * The number to display is read from the Serial Input
 * either type the number in the Serial Monitor
 * or via, for example, Bluetooth.
 * 
 * Only numbers are displayed, but negative 
 * and decimal fractions can be displayedz
 * 
 * For numbers less than zero, for example 0.125
 * must have a leading zero, ie 0.125 and not .125
 * 
 * The LED display can be cleared by sending any letter
 * 
 **********************************************************/
#include "LedControl.h" 
LedControl lc=LedControl(12,11,10,1);
int number[8];
int numLength = 0; // number of digitss
int i = 0;
int dp = 0; // position of decimal point, if any
int j = 0;
boolean minusSign = false; // false if negative number
boolean valid = false;
double displayNumber = 0;
String stringNumber;
void setup() {
  /*
   The MAX7219 is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);
  /* Start Serial Monitor */
  Serial.begin(9600);
}

void printDigits() {
lc.clearDisplay(0);
for(i=0;i<numLength;i++) {
if( dp == numLength-i){
lc.setDigit(0,i,number[numLength-(i+1)],true);
}
else{
lc.setDigit(0,i,number[numLength-(i+1)],false);
}
}
}
//
void loop() {
if(Serial.available()){
j = 0;
numLength = 0;
dp=0;
stringNumber ="";
}
// get number to display
while (Serial.available()){
delay(10);
int a = Serial.read();
stringNumber = stringNumber + char(a);
if((a>47 && a< 58) || a == 45){ // ignore line end and decimal point
a = a - 48;
number[j] = a;
numLength=numLength+1;
if(numLength > 8){
numLength = 8; // stop overflow
}
j = j +1;
}
if(a == 46) { // decimal point
dp = numLength;
}
printDigits();
valid = true;
}
// check for a minus
if (number[0] == -3){
lc.setRow(0,numLength-1,B00000001); // print a minus sign
}
if(valid == true){
Serial.println(stringNumber); // this is the string sent to the Serial Port.
valid = false;
}
}