EDITS: 6/11/19 - Fixed broken links; Added link to Part Eight.
I'm going with an Arduino interface to display voltage, current, power and temperatures. In the first version this will be display only - controls for setting voltage and current limits are manual (10 turn potentiometers) - but can be extended with more functionality in the future.
The 4Duino from 4D systems is an Arduino compatible (Leonardo I believe) device with a built in touch-enabled LCD, wifi and SD card reader. It comes in a number of sizes and this project uses the 2.4" version.
In the box we find a number of headers and connectors. This is the starter kit version: in addition to the module and headers, which come with the standard version, there is also a programming adaptor, a 5-way F-F ribbon cable with M-M adaptor and 4GB microSD card (not shown, I missed it initially in the packaging!)
For prototyping, I just want to get together the code to read thermistors and voltage and current flow. First things first though, the headers need soldering to the module: they come separately so that you can attach wires directly or different headers (e.g. angled ones) if you prefer - I will be using crimped leads so on they go:
First impressions are really positive: it's well packed and the datasheet is very comprehensive. It's not a big chore to solder on the headers - about 10 mins work. A novice to soldering would be advised to take it steady: those headers need to be perpendicular if you want to add a Shield on, otherwise you will struggle to engage the pins. My suggestion is to hold them against the board with blu-tac or similar to make sure they stay put during the process. The datasheet has some good instructions.
Getting Started
The 4Duino, unlike the Arduino Uno I'm more familiar with, runs only from a regulated 5V supply supplied to Vin, USB port or barrel jack: a diode pair uses the input with highest voltage if there is more than one connection. On a Uno it seems possible to power the board through the +5V pin as well: that won't work here. One potential drawback of the board could be that the 5V pin will only supply Vin - 0.3V so if you need to drive a 5V regulated circuit from the board you'd have to sail Vin very close to the wind with it's max input voltage of 5.5V. Fortunately I don't need to do that.
Your computer's USB port should provide a regulated supply. If you're connecting to Vin I would recommend that you double check the regulated output first to be double sure it is under the 5.5V limit.
Programming can be done via the Arduino IDE (100% compatible) or 4D systems proprietary IDE, Workshop4. The latter is only available for Windows so if you are on MacOS or Linux then Wine/Crossover or virtualisation software is necessary. It's worth thinking about what you want to achieve:
- Arduino IDE: basic functionality achieved through a Picaso serial library and wifi command set. For simple interfaces and usage this may be enough and comes with the familiarity of the IDE.
- Workshop 4: This allows for greater exploitation of the board giving three development environments:
- Basic graphics: uses native arduino code with graphic primitives. No access to uSD card
- Extended graphics: a visual programming environment with drag-and-drop graphical objects. Uses the uSD card to hold the graphics
- Genie graphics: seems to build on extended graphics with the inclusion of event-driven actions. Noted as 'coming soon'.
For the purposes of prototyping the display, what I want to achieve is a base-level of code with data written to the LCD. I'll do that with the native Arduino IDE for now. Later, I intend to develop the interface further and will be able to comment more on the Workshop4 software (and its compatibility with Wine/Crossover.)
Connecting the 4Duino to my iMac requires a microUsb cable. Guess what isn't provided in the box? Guess how many USB cables I have access to and the subset of those that are microUsb? Fortunately, I have one out of the dozens of cables I have but it's worth bearing in mind. Frankly, at these prices I think one should be provided in the starter kit.
As far as I can tell, the only way to use the Arduino IDE is as a standalone app - there doesn't appear to be a way to add the 4Duino to the acceptable boards list in the online editor. Download and install it, add the necessary json file to the board manager - full instructions are on the 4D systems website. This document provides a guide to using the display in serial mode which is all that is needed here - basically, it's an introduction and a complete set of commands to send to the Picaso processor which handles the screen.
INA260 Adaptor Board
To test the code for Voltage and Current readings I need to solder a TI INA260 IC to an adaptor board - a TSSOP-16 to DIP-16. Here's the kit from CPC:
It looks like good quality: the headers have two pins on one side as they 'surface mount' to the bottom. The clear plastic is a spacer to ensure they solder onto the board at the correct distance apart to plug into a breadboard or prototype board. Post soldering:
I got hold of a SMD flow tip - hoof tip - for my Hakko FX-888D (from Mouser, not available on Farnell), one with a dimple on the tinned surface. I tried it and failed miserably with it - just too big and I couldn't get it to properly connect with pins and pad and buckets of flux didn't help. There's clearly a technique to learn as it seems a popular approach. Anyway, got there with my standard 1.2mm tip. Testing the pins for bridging I was a bit annoyed to find pins 1,2,3 and 14,15,16 were bridged. A quick wipe with solder wick and....still bridged. Then I remembered that these pins are internally connected - I really don't know how I've made it this far!! After soldering on the headers, it fits in the breadboard and I can verify pin connections and no bridging.
Prototype Schematic
In the build I will be measuring the temperatures of the LT3081s; the bridge rectifier, Mosfet and case temperatures and the voltage and current draw of the connected load through an INA260 IC from Texas Instruments. The prototype will test all this with breadboard mounted components and the simply power supply I already created (see Post One - Introduction.) It can provide both the regulated 5V I need plus up to 12V on a separate connection. Here's the schematic:
The load is a power resistor I purchased for testing purposes - 10Ohm at 100W. My supply is limited to 1A at 9V and 0.9A at 12V. I'll run the voltage at 9V with this load. Changing the load resistor to different values will allow me to manage the current drawn from the supply and I can then increase the supply voltage to 12V.
The breadboard is shown below. I use red wires to indicate power; black wires to indicate ground and other colours for signal. I've removed the original image and substituted the one below which includes the INA260 on its adaptor (the substituted one was the same just without the adaptor.)
5V and Ground run down the right hand rail and 9V and Ground down the left hand rail (power on red, ground on black) - ground is linked across the bottom of the breadboard. I use red for direct connections to a power rail and black for a direct connection to GND; other colours are signal wires. On the right hand rail, the red and black dupont leads go to the 4Duino Vin and GND to power it. The yellow, orange and green dupont wires go to A0, A1, A2 on the 4Duino: this provides the input voltage for the thermistors and thus temperature calculation. The white and blue dupont leads go to the 4Duino SDA and SCL pins - this will allow readings of voltage, current and power. The yellow lead from the INA260 that snakes around it, leads to the load: in this image a 470Ohm resistor to take the place of the 10Ohm/100W noted in the schematic to make it easier to photograph. In my testing I will probably make use of different load resistors to measure current changes.
Measuring the actual voltages supplied to the board by my simple supply gives 9.120V and 4.988V. The 5V actual and for the 10K Ohm series resistors actuals, for the thermistors, are reflected in the code below to improve accuracy.
The code
It's not obvious from the document mentioned above how to get the board setup, but fortunately there is an example application to work from. Or so you'd think: that example application is wrong! Seriously, they've had a number of years to get that fixed - it's a pain because to fix it, you have to scavenge around to find the right existing Project from their website as there is no information in data sheets or manuals. Anyway, the code below is hopefully pretty self-explanatory as it is simple at this stage. Currently, it is monitoring:
- the Thermistors and displays the Analog reading (average of 5 samples); thermistor resistance; voltage conversion; and temperature calculated with the Steinhart-Hart equation. An obvious alternative would be to hold a table of resistance/temperature values for a suitable range and perform a look up. I don't need that level of accuracy however.
- the Voltage, Current and Power averaged over 5 samples. The Power is a calculation within the IC: Voltage * Current.
/* Simple prototype for the 4Duino using three thermistors and an INA260.
* These form part of the monitoring of the final build and this code should form the basis of a graphical build
* as part of the final version.
* Prototype is using simple print/println commands
*/
// For SDA/SCL connections
#include <Wire.h>
// Picaso display libraries
#include <Picaso_Const4D.h>
#include <Picaso_Serial_4DLib.h>
#define DisplaySerial Serial1
Picaso_Serial_4DLib Display(&DisplaySerial);
// Thermistors - references in schematic
#define TH1 A0 // analog pin connected
#define TH2 A1 // analog pin connected
#define TH3 A2 // analog pin connected
// Resistors - measured with DMM - references in schematic
#define R1 10065
#define R2 9948
#define R3 9909
#define SOURCEVOLTAGE 4.988 // nominal 5V in, measured with DMM
#define THERMISTORNOMINAL 10000.0 // resistance at 25C
#define TEMPERATURENOMINAL 25.0 // degrees centigrade
#define BCOEFFICIENT 3950.0 // beta coefficient from datasheet
#define NUMSAMPLES 5 // Improve calculation efficiency by averaging reads over a number of samples
void setup() {
setupLCD();
setupINA260();
}
void setupLCD() {
Display.Callback4D = mycallback; // For handling errors
Display.TimeLimit4D = 5000; // 5secs timeout on all commands
DisplaySerial.begin(200000);
delay(5000); // let the display startup
Display.gfx_ScreenMode(LANDSCAPE);
}
void setupINA260() {
// write to the INA260: Address:Register:High Byte:Low Byte
// See datasheet for values
Wire.begin();
Wire.beginTransmission(0x40); //address set by A1 and A0 pins on INA260
Wire.write(0x00); // config register
Wire.write(0x61); // high byte -> take 1 average
//Wire.write(0x65); // high byte -> take 4 averages
Wire.write(0xb7); // low byte -> conversion time for voltage and current = 4.156 ms (average out the data for low noise), and opperate in continous mode
Wire.endTransmission();
}
void loop() {
// Clear the screen and display the temperature from each thermistor in turn.
// Followed by V,I,P from INA260
// The 10 second delay is to give a chance to read it.
Display.gfx_Cls();
DisplayTemperature(TH1, R1);
DisplayTemperature(TH2, R2);
DisplayTemperature(TH3, R3);
DisplayVoltage();
DisplayCurrent();
DisplayPower();
delay(10000);
}
/*
Return an averaged reading from the Thermistor voltage divider
*/
float ReadThermistor(int pin) {
uint8_t i;
float average;
float samples[NUMSAMPLES];
for (i = 0; i < NUMSAMPLES; i++) {
samples[i] = analogRead(pin);
delay(10); // spread readings out otherwise they are likely to be the same value or very close
}
average = 0;
for (i = 0; i < NUMSAMPLES; i++) {
average += samples[i];
}
return average / NUMSAMPLES;
}
/*
Displays values associated with the passed Thermistor and series resistance
*/
void DisplayTemperature(int thermistor, long seriesResistor) {
float reading;
float resistance;
// Obtain reading from thermistor
reading = ReadThermistor(thermistor);
Display.print("Analog reading TH");
Display.print(thermistor - 13); // Analog Pins seem to have an int value starting at 14.
Display.print(": ");
Display.println(reading);
// Convert the value to a resistance at the current temperature
resistance = (1023 / reading) - 1.0;
resistance = seriesResistor * resistance;
Display.print("Thermistor resistance: ");
Display.println(resistance);
// Calculate voltage at the divider - for xref against a multimeter connected at the voltage divider
float vout = (SOURCEVOLTAGE * resistance) / (seriesResistor + resistance);
Display.print("Voltage read: ");
Display.println(vout);
// Calculate and display temperature
Temperature(resistance);
}
/*
Calculate the temperature based on the Steinhart-Hart equation.
An alternative would be to hold a table of resistances/temperatures from the datasheet.
Must consider memory usage.
*/
void Temperature(float resistance) {
float steinhart;
steinhart = resistance / THERMISTORNOMINAL;
steinhart = log(steinhart);
steinhart /= BCOEFFICIENT;
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15);
steinhart = 1.0 / steinhart;
steinhart -= 273.15; // convert to C
Display.print("Temperature: ");
Display.print(steinhart);
Display.println(" *C");
Display.println("");
}
void DisplayVoltage() {
double dVoltage = 0.0;
// ask for voltage readings
Wire.beginTransmission(0x40); // Address
Wire.write(0x02); // Bus Voltage Register
Wire.endTransmission();
dVoltage = ReadData(1.25);
// Display
Display.print("Voltage: ");
Display.print(dVoltage, 3);
Display.println("V");
}
void DisplayCurrent() {
double dCurrent = 0.0;
// ask for current readings
Wire.beginTransmission(0x40); // Address
Wire.write(0x01); // Bus Voltage Register
Wire.endTransmission();
dCurrent = ReadData(1.25);
// Display
Display.print("Current: ");
Display.print(dCurrent, 3);
Display.println("A");
}
void DisplayPower() {
double dPower = 0.0;
// ask for power readings
Wire.beginTransmission(0x40); // Address
Wire.write(0x03); // Bus Voltage Register
Wire.endTransmission();
dPower = ReadData(10.0);
// Display
Display.print("Power: ");
Display.print(dPower, 3);
Display.println("W");
}
/*
* Read NUMSAMPLES values from the preset register (for V, I or P) and average them.
* The LSB size represents the LSB size as stated in the datasheet.
*/
double ReadData(float lsbSize) {
long total = 0;
int value = 0;
double dValue = 0.0;
total = 0;
for(int i = 0; i < NUMSAMPLES; i++){
Wire.requestFrom(0x40, 2); // Read two bytes
delay(5);
if (2 <= Wire.available()) {
value = Wire.read(); // receive high byte (overwrites previous reading)
value = value << 8; // shift high byte to be high 8 bits
value |= Wire.read(); // receive low byte as lower 8 bits
total += value;
}
}
// Turn into high precision and average them and convert to Volts
dValue = total;
dValue = ((dValue * lsbSize) / 5.000) / 1000.000;
return dValue;
}
/*
* Simple error handling: flash an LED.
*/
void mycallback(int ErrCode, unsigned char Errorbyte)
{
// Pin 13 has an LED connected on most Arduino boards. Just give it a name
int led = 13;
pinMode(led, OUTPUT);
while(1)
{
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for 200 ms
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for 200 ms
}
}
Results (early testing)
Actual temperatures, from two guages are 24.0C and 23.8C. The images below are from when I was powering the breadboard from the 4Duino rather than a power supply (the 4Duino was powered via USB from my iMac). I've left them in to show the accuracy that can be achieved this way
The calculated temperatures are below:
It looks like I am within 0.5C which is good enough for monitoring purposes. I'm hoping I can get this a little more accurate by tuning the voltage and resistances a little more. Given I can't create a perfect 25C environment for the thermistors, I can't accurately measure their nominal resistances at that temp so for now they stick at 10K Ohm. A quick test with an external regulated 5V supply driving the 4Duino and thermistors is giving worse results so I need to do more investigation on that - I'm waiting on a couple of parts. A typical approach would be to power the 4Duino at 5V and power the thermistors from its 3.3V and using that as the analog reference voltage - it's a lot less noisy. I won't be able to do that in this version of YAPS.
Results (Full Testing)
The readings from the INA260 look pretty accurate when compared against a multimeter:
Sorry, not a brilliant photo but it's difficult to get it all in. What it is showing:
- Fluke is measuring voltage: 8.981V
- Extech is measuring current: 18.94mA
- 4Duino is showing: 8.998V 0.016A 0.018W
It would be hard to say which is most accurate but the discrepancy is about 10mV and 3mA. The Power value is way off: clearly something wrong with the code so back we go.
For the temperatures:
This is now reading way off:
- Hive is showing 25.2C
- Clock is showing 24.8C
- 4Duino is showing: 28.83C 28.92 29.19C
I would assume there will be some variation in the thermistors themselves (in the code I've taken account of the series resistors actual resistances and actual voltage supplying them.) However, the calculated temperature is 4C too high - that I need to improve. Checking the display resistance against the datasheet, the temperature that is displayed is pretty much correct (for example, 8453Ohms is between 28 and 29C in the datasheet.) Also, if I use the displayed resistances (10000Ohms for 25.2C) with information from the datasheet on this site, it calculates the temperature at 28.48C. I think the code is correct so it must be the analog to digital conversion within the 4Duino. Note that it isn't 28C in this room - I think Hive and clock are accurate. The tips of the thermistors are way above the breadboard as well so unless there is a funnel of rising hot air then they should be at the same ambient temperature as Hive and Clock.
It may be that the regulated 5V I supply is noisy; it may be that the ADC in the 4Duino is being affected by noise from its internals (usually why you can set AREF to the 3.3V supply directly from the 4Duino / Arduino.) Back to research and the code base. I have just taken delivery of a DC-DC switching regulator that can replace the LM7805, recommended by shabaz, so I will try that in the circuit.
More to come but I'll post as comments rather than keep updating this post.
Top Comments