Voltage sensor for Arduino.

  

I use these voltage sensors to monitor a battery pack used to power an Arduino. They are nothing more than two resistors wired as a voltage divider, but at less than £1 on eBay they are easy to use.

The Arduino Analogue inputs can take a voltage of up to 5 volts, these voltage sensors use a 5:1 voltage divider and this means that voltages up to 25 volts will be reduced to below 5 volts. All we have to do is measure the reduced voltage then multiply the result by 5 to get the original voltage. This means you can power the Arduino with a 9 volt battery and monitor the battery voltage.

The sketch shown below is a simple example of how voltage can be measured. Take care, there is no reverse protection, so if you connect the voltage incorrectly it may damage the Arduino. Make sure the voltage you are measuring is less than 25 volts.

Two factors effect the accuracy of the result. The sketch assumes the Arduino’s Vcc is 5 volts, check this with a volt meter and adjust the variable Vcc accordingly. The second factor is the actual division provided by the voltage divider. The voltage shield shown at the top of the page has a factor of 4.092. If you build your own divider from two resistors, I used 15k and 3k3, then calculate the factor by adding the two resistors together and dividing the result by the smallest value resistor. 


// Voltage Probe - Max input is 25v
// NO REVERSE PROTECTION. Make sure its wired up correctly!!!
// Uses 3.3k and 15k resitors in series (3.3k goes across A0/GND)
//

// The factor is (R1+R2)/R2
// Example R1 = 15k, R2 = 3.3k, factor is 18.3/3.3 = 5.54

double Vout; // voltage at pin A0
double Vin; // voltage being measured, max = 25v
double factor = 4.54;
double Vcc = 5.00; // this is the Arduino's Vcc, measure and adjust if necessary

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


void loop() {
Vout = analogRead(0); // read the adjusted voltage 0 to 1023
Vout =(Vout/1023)*Vcc; // convert to a voltage 0 - 5 volts
Vin = Vout * factor; // convert to the voltage being measured
Serial.print("Voltage= ");
Serial.print(Vin);
Serial.println("v");
delay(1000);
}


Advertisements

Measuring the Broadcom chip temperature on the Raspberry Pi

The electronic package for my weather balloon project is now complete and housed in a lightweight plastic cage. I have reduced heating problems by using 25 cm male to female USB connectors to connect the LPRS radio and the GPS/FTDI to the Raspberry Pi, now the 4 way USB block runs at a reasonable temperature. I can monitor the internal temperature of the LPRS radio and the ambient temperature, but I was concerned that in the cramped conditions in the container the Broadcom chip may overheat. Early experiments with the Pi in a case and all four USB sockets used showed that the system would behave erratically as the temperature rose above 30C.

A quick scan of the Internet seemed to show that although the Broadcam chip has temperature sensors they could not easily be accessed. However, it seems that although this was true in early versions of the Raspberry Pi later versions allow the temperature to be read. Open a terminal window and type in the following:

/opt/vc/bin/vcgencmd measure_temp

and receive the reply

temp=48.7'C

Using

/opt/vc/bin/vcgencmd measure_temp| egrep "[0-9.]{4,}" -o

Will just return

48.7

My Python code sends ACK after each requested data has been sent back to the master unit and I intend to add the Broadcom temperature to this monitor the Raspberry Pi.

Using the code with Python

To use this code with Python use the following:

include os

cmd = '/opt/Vcc/bin/vcgencmd measure_temp'
coreTemp = os.popen(cmd).readline().strip()

This will return a string similar to

temp = 44.6'C

If you need just the temperature value you can add the following line to the above

temperature = coreTemp.split('=')[1].split("'")[0]

temperature will then contain the value. It seems the Broadcom processor runs at about 40 to 50’C, but could operate up to about 80’C.

DDS AD9851 and Arduino

  

Direct digital synthesizer is a type of frequency synthesizer used for creating arbitrary waveforms from a single, fixed-frequency source. The AD9850 is a low cost device that can produce sine waves up to 125 mHz and the output frequency is set digitally using an MCU, such as an Arduino.

In addition to Gnd and 5 volts only four connections are required and these are shown in the sketch below. When I first obtained this device I could find very little information, but eventually came across this sketch. I quickly got it up and running and the picture shows an oscilloscope trace taken from the output Sine A.

/*
* A simple single freq AD9850 Arduino test script
* Original AD9851 DDS sketch by Andrew Smallbone at http://www.rocketnumbernine.com
* Modified for testing the inexpensive AD9850 ebay DDS modules
* Pictures and pinouts at nr8o.dhlpilotcentral.com
* 9850 datasheet at http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf
* Use freely
*/

#define W_CLK 8 // Pin 8 - connect to AD9850 module word load clock pin (CLK)
#define FQ_UD 9 // Pin 9 - connect to freq update pin (FQ)
#define DATA 10 // Pin 10 - connect to serial data load pin (DATA)
#define RESET 11 // Pin 11 - connect to reset pin (RST).

#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }

// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data)
{
for (int i=0; i<8; i++, data>>=1) {
digitalWrite(DATA, data & 0x01);
pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high
}
}

// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) {
int32_t freq = frequency * 4294967295/125000000; // note 125 MHz clock on 9850
for (int b=0; b<4; b++, freq>>=8) {
tfr_byte(freq & 0xFF);
}
tfr_byte(0x000); // Final control byte, all 0 for 9850 chip
pulseHigh(FQ_UD); // Done! Should see output
}

void setup() {
// configure arduino data pins for output
pinMode(FQ_UD, OUTPUT);
pinMode(W_CLK, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(RESET, OUTPUT);

pulseHigh(RESET);
pulseHigh(W_CLK);
pulseHigh(FQ_UD); // this pulse enables serial mode - Datasheet page 12 figure 10
}

void loop() {
sendFrequency(10.e6); // freq
while(1);
}

Installing Gnuplot on the Raspberry Pi

Gnuplot produces graphs from a file with the extension .dat Install Gnuplot on the Raspberry Pi using the following command

sudo apt-get install gnuplot-x11

answering Y when required. Once Gnuplot is installed the following python programme can be used to generate some data.


#!/usr/bin/python

import math

f = open('mydata.dat', 'w')

# Loop

for degrees in range(720):
    # Generate data points
    si = math.sin(math.radians(degrees))
    # Write 3 data points to text file
    data = "{} {}\n".format(degrees, si)

    f.write(data) 

f.close()

Run the code using

sudo python gnuplot_generate_data.py

and this will generate a file that can be used by Gnuplot. Now open a terminal window and type in

gnuplot

The program will start and at the prompt type

plot "mydata.dat"

and the graph will be plotted

 

It is possible to change axis, add titles and much more.  A good guide as to what can be achieved with Gnuplot can be found here.

DHT11 Humidity Sensor and Raspberry Pi

  

The humidity sensor, DHT 11, is the last sensor to be added to my Weather Balloon project. The board I am using is shown above, a resisistor is already connected between Vcc and the Output and so only three connections, Vcc, Output and Gnd are required. The sensor will operate at 3 volts as long as the connections are kept short.

I followed the Adafruit instructions found here. Once everything was installed I needed to use Python code to add to my existing code for the weather balloon. One of the examples in the Adafruit library was almost exactly what I required, but was designed to run from a command line, for example

AdafruitDHT.py 11 4

Where 11 is the sensors number (use 22 for the DHT22) and 4 is the GPIO pin used. The  DHT11 is connected to pin 7 (Output), pin 17 (3.3 volts) and pin 20 (Gnd). 

I modified the AdafruitDHT.py code by removing the part that collects the device number and GPIO pin from the command line

import sys

import Adafruit_DHT

# I am using a DHT11 on GPIO pin 4
humidity, temperature = Adafruit_DHT.read_retry(11, 4)

if humidity is not None and temperature is not None:
print 'Temp = {0:0.1f}*C  Humidity={1:0.1f}%'.format(temperature, humidity)
else:
print 'Failed to get reading. Try again!'

The code can now be run from within a python programme.

Opto Switch Slotted Sensor Shield and Arduino

  

I intend to use this board in an NBTV project to measure the speed of the Nipkow disk. This is normally done by having slots cut in the disk and shining an IR LED through to be picked up by a photo diode on the other side.

The connections (looking down on the board with the connections at the bottom) are Gnd, Analog Output, Digital Output and Vcc. I have used a slightly modified sketch that I used with an LDR shield. Arduino Analog Pins A0 and A3 are set as Digital Output Pins to provide the power supply. Pin A1 is set as a Digital Input and pin A2 is set as an Analog Input.

Upload the sketch, then remove the power, connect the shield as shown in the picture above and reconnect the power and the PWR LED will light. Use a piece of card to interrupt the beam, the Output LED will turn Off and On, the Serial Monitor Output is shown here.

  

When the beam is broken the Output goes High and the OUT LED lights up. When using this as a Tachometer the Digital output would normally be used. Here is the sketch I used to test the board, but before using it make sure your connections are the same as mine.

/*
* Opto Slotted Switch Test Sketch
*
* Pins
* Vcc to A0
* DO to A1
* AO to Arduino pin A2
* Gnd to A3
*/

int analog = 16; // Arduino A2
int digital = 15; // Arduino A1
int gnd = 17;  // supplies 0 volts
int power = 14;  // supplies 5 volts

void setup() {
 Serial.begin(9600); // start Serial Monitor
 pinMode(13, OUTPUT);
 digitalWrite(13,LOW);  // turn OFF the LED on Arduino pin 13
 pinMode(digital, INPUT);  // this pin reads the digital output, either HIGH or LOW
 pinMode(power, OUTPUT);
 digitalWrite(power,HIGH);// this pin will supply 5 volts
 pinMode(gnd, OUTPUT);
 digitalWrite(gnd,LOW); // this pin will supply the GND to the board
}

void loop() {
 // print the analog output in milli volts
 Serial.print("Analog level = ");
 Serial.print(analogRead(analog));
 Serial.println(" mv");  // milli volts
 // print the digital Output LOW = alarm tripped
 Serial.print("Digital level =");
 if (digitalRead(digital) == HIGH){
   Serial.println(" HIGH");
 }
 else{
   Serial.println(" LOW");
 }
 delay (1000);  // this just makes it easier to read the serial output

Using the Ublox NEO 6 GPS and Compass board

The picture shows the Compass connected to an Arduino Uno. The compass uses a four pin socket, I cut the plug off the other end and soldered a four pin header plug instead. This board must only be powered with 3.3 volts and the data lines must also be connected to the Arduino via a 5volts to 3.3 volts logic level converter. I use one I obtained from Hobbytronics here that has a 250ma 3volt regulator that can power the GPS board.

Testing the Compass: Four connections are required, Gnd, SDA, SCL and 3.3 volts. It seems that the GPS and Compass are powered separately and two logic level converters will be required. The Compass uses SDA and SCL, analog pins 4 and 5 on the Uno. Once the hardware is connected and the wiring checked  download the two libraries from Adafuit page for the HMC 8553L here, but remember this board, unlike the Adafruit board, must be used only at 3.3 volts and the board does not have a Ready pin. Copy the two libraries to your library folder and restart the Arduino IDE, upload the sketch from the Example folder and switch to the Serial monitor. If all is well you should see something like this

The bearing will only be true if the Compass chip faces up, this will mean that the Ceramic Active Aerial will be facing downwards. If the board is turned so that the Aerial faces upwards (the correct position) the compass reading will be wrong. The Adafruit article shows how this can be corrected. Keep the compass level and rotate the board to see the heading change. On my board the direction for the bearing seemed to be the board edge with the GPS socket. This edge should face forward when mounted in a vehicle.

Testing the GPS: I disconnected the HMC8553L plug and connected the six pin GPS plug. Only four pins are connected and these are in exactly the same order as on the Ublox NEO 6 board, Gnd, Tx, Rx and Vcc (Gnd is closest to the GPS component. I used the Adafruit GPS library from here. Copy the library to your Arduino Library folder and restart the Arduino IDE. Use a 5 volt to 3.3 volt Logic Level Converter, this board cannot be used with 5 volts. Connect Gnd and 5 volts from the Arduino to the Logic Level Converter, the Adafruit sketch uses Software Serial on pins 2 and 3. The GPS Rx pin is connected to pin 2 and the GPS Tx pin is connected to the Arduino pin 3 (through the Logic Level Converter). The GPS is powered from the Gnd and 3.3 volt pins on the Logic Level Converter, this time the board’s power LED will light.

Open the Example folder and upload the Echo Sketch this simply prints the output from the GPS on the Serial Monitor and is useful because even without a signal the GPS will output data and so the board can be tested indoors. Outside the GPS acquired a first time fix in less than two minutes.

The next task is to get the board running on the Raspberry Pi and to be able to read both the GPS and Compass at the same time.