element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Members
    Members
    • Achievement Levels
    • Benefits of Membership
    • Feedback and Support
    • Members Area
    • Personal Blogs
    • What's New on element14
  • Learn
    Learn
    • eBooks
    • Learning Center
    • Learning Groups
    • STEM Academy
    • Webinars, Training and Events
  • Technologies
    Technologies
    • 3D Printing
    • Experts & Guidance
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Arduino Projects
    • Design Challenges
    • element14 presents
    • Project14
    • Project Groups
    • Raspberry Pi Projects
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Or choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
Personal Blogs
  • Members
  • More
Personal Blogs
Legacy Personal Blogs YAPS Part Seven - Prototyping of Arduino Interface
  • Blog
  • Documents
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Blog Post Actions
  • Subscribe by email
  • More
  • Cancel
  • Share
  • Subscribe by email
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Andrew J
  • Date Created: 5 Jun 2019 12:56 PM Date Created
  • Views 814 views
  • Likes 6 likes
  • Comments 5 comments
  • arduino project
  • bench power supply
  • modular_bench_powersupply
Related
Recommended

YAPS Part Seven - Prototyping of Arduino Interface

Andrew J
Andrew J
5 Jun 2019

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.

image

 

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!)

image

image

 

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:

image

 

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:

image

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:

imageimage

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:

image

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.)

image

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

image

The calculated temperatures are below:

image

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:

image

Sorry, not a brilliant photo but it's difficult to get it all in.  What it is showing:

  1. Fluke is measuring voltage: 8.981V
  2. Extech is measuring current: 18.94mA
  3. 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:

image

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.

 

Next: Part Eight - Prototyping the Power Stage

Back: Part Six - Design - BOM

  • Sign in to reply

Top Comments

  • shabaz
    shabaz over 4 years ago +2
    Hi Andrew, This is great seeing the 4D systems display/controller and the code. The 4D systems stuff looks fantastic, I saw some of their displays at an exhibition, and the latest generation ones look…
  • Andrew J
    Andrew J over 4 years ago in reply to shabaz +2
    Yes, I'm really enjoying it. Like I said to Donald, I'm learning a lot but I'm out of my comfort zone and really feeling like there's stuff here that I don't know I don't know - if that makes sense. Not…
  • three-phase
    three-phase over 4 years ago +1
    This is a very interesting series to follow along with, I look forward to seeing you complete the project. Kind regards.
  • Andrew J
    Andrew J over 4 years ago in reply to shabaz

    Yes, I'm really enjoying it.  Like I said to Donald, I'm learning a lot but I'm out of my comfort zone and really feeling like there's stuff here that I don't know I don't know - if that makes sense.  Not silly mistakes like miscalculating the thermal requirements for the LM7805, but everything I seem to read warns about parasitics, inductance, capacitance, ESR, ground loops etc etc.  A lot of my confidence is coming from (a) spotting the mistakes in the original design and fixing them; and (b) getting a working LTSpice model that behaves as I would expect.  If the latter works accurately, which I hope it does, then it should be ok - the only issue being of course it models 'perfect' components rather than real-world components.  I guess I'll soon find out!

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 4 years ago

    Hi Andrew,

     

    This is great seeing the 4D systems display/controller and the code.

    The 4D systems stuff looks fantastic, I saw some of their displays at an exhibition, and the latest generation ones look very cool.

    I recently tried a cheap ebay display, while it works, it isn't a top-quality screen and suffers from poor viewing angles.

    Also, it is very cool that you're using the Steinhart-Hart equation to get accurate temperature conversions.

    It's nice seeing designs with such a screen, since there is a lot of information that can be gleaned from your sensors, and it's fun trying new things like this, deciding how the UI should look, and what functionality to have!

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Andrew J
    Andrew J over 4 years ago

    Now we're cooking on gas!

     

    I've made a few updates to the code to improve accuracy. 

     

    Firstly, the Voltage, Current and Power - the mistake I made initially with the power reading was ignoring the 10mW LSB value the INA260 holds - accounting for that brings it into expectation.  All values have some LSB size to take account of:

    • Voltage: 1.25mV
    • Current: 1.25mA
    • Power: 10mW  I suppose I could just take the Voltage and Current values and work out the power myself, save a read etc. 

    image

    The Fluke is measuring Voltage; the Extech Current.  What we are seeing:

    • Fluke: 5.4840V
    • Extech: 11.44mA
    • 4Duino: 5.488V; 0.009mA; 0.050mW reported (against a P=VI calculation of 0.049mW)

    I'd say that was pretty good!  2mA of current off.  The datasheet for the INA260 states it has a 5mA offset maximum and a current sense gain error of 0.2%typical to 0.5%max.  That wouldn't count for it all but I'm also measuring that current through 2" of hookup wire.  It's accurate enough.

     

    Secondly, the temperature readings.  I was right in that the culprit in the inaccuracy was the nominal 5V Vin on the 4Duino.  That's used as a reference in the analog reading conversion: if it isn't precisely 5V then the conversion is off.  Even providing it with a regulated 5V supply isn't going to give that level of accuracy and it will always fluctuate somewhat.  In fact, the voltage supplied is a few 10's of mV lower than 5V causing the analog reading to go high - hence the higher temperature readings displayed.

     

    Here's what I show now:

    image

    • Hive is showing: 22.6C
    • Clock is showing: 22.1C
    • 4Duino is showing: 22.26C; 22.78C; 22.33C

    I can definitely live with that accuracy!  I made two changes to the code.  Firstly, when taking the analog reading I also took a Vcc reading using the ATMega32U4 internal voltage reference of 1.1V.  I then used that reference to accurately convert the analog reading into a voltage reading.  This bypasses the conversion using the 5V 'perfect' supply.  Secondly, although minor, I changed the Steinhart Hart calculation to use a more accurate equation incorporating coefficients from the datasheet.  I've only used those applicable to a range of 50.5C to 103C and could squeeze a little more accuracy by including the range from -2C to 50.5C but I don't think that's necessary: I think a fraction of a degree discrepancy is accurate enough, will always be subject to the actual resistances of the Thermistors (which I can't be bothered to calibrate) and it's impossible to say which of the 3 Thermistors, Hive and Clock are the correct reading in any case.

     

    You'll also notice that the display shows a Control Temperature: this is actually a specific resistance taken from the datasheet and pushed through the calculation to make sure it was accurate - the answer for 8766Ohms should be, and is, 28C.  As an aside, Excel calculated it out at 26.somethingC which led me down a lot of pointless cross-checking.  There's something screwy within its calculation I'm sure - possibly the logarithm function.

     

    I'm really happy with that.  The final display I want to incorporate graphics and the like but I now have something to test the build against.

     

    Latest Code

    /*  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 THERMISTORNOMINAL 10000.0 // resistance at 25C

    #define TEMPERATURENOMINAL 25.0   // degrees centigrade

    #define CONTROLRESISTANCE 8766    // This should calculate a temperature of 28C

    #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 operate 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);

      Display.println("Control Temperature");

      Display.print("Control Resistance: ");

      Display.println(CONTROLRESISTANCE);

      Temperature(CONTROLRESISTANCE); // Lets check we see 28C with the calculation

     

      DisplayVoltage();

      DisplayCurrent();

      DisplayPower();

     

      delay(10000);

    }

     

    /*

    * Obtain the actual Vcc value of the 4Duino from an internal reference source.

    * The nominal 5V Vin can fluctuate a lot and affect analog read accuracy.

    */

    long readVCC() {

      long result;

      // Read 1.1V reference against AVcc

      ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);

      delay(2); // Wait for Vref to settle

      ADCSRA |= _BV(ADSC); // Convert

      while (bit_is_set(ADCSRA, ADSC));

      result = ADCL;

      result |= ADCH << 8;

      result = 1126400L / result; // Calculate Vcc (in mV); 1126400 = 1.1*1024*1000

      return result;

    }

     

    /*

      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++) {

        int value = analogRead(pin);

        float supply = readVCC() / 1000.0; // obtain vcc at time of read

        float valueCorrected = supply / 5 * value; // improve the accuracy of the analog reading

        samples[i] = valueCorrected;

        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;

      float vOut;

     

      // 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 = seriesResistor * (1024.0 / reading - 1.0);

      Display.print("Thermistor resistance: ");

      Display.println(resistance);

     

      // Calculate and display temperature

      Temperature(resistance);

    }

     

    /*

      Calculate the temperature based on the Steinhart-Hart equation.

      Coefficients are from the datasheet

      An alternative would be to hold a table of resistances/temperatures from the datasheet.

      Must consider memory usage.

    */

    void Temperature(float r2) {

      float temperature;

      double coeffA = 3.354016e-03;

      double coeffB = 2.541522e-04;

      double coeffC = 3.730922e-06;

      double coeffD = -7.881561e-08;

      double logR2 = 0.0;

     

      logR2 = log(r2/THERMISTORNOMINAL);

      temperature = (1.0 / (coeffA + coeffB*logR2 + coeffC*logR2*logR2 + coeffD*logR2*logR2*logR2));

      temperature -= 273.15;

     

      Display.print("Temperature: ");

      Display.print(temperature);

      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);    // Voltage is accurate to 1.25V

     

      // 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);    // Current is accurate to 1.25mA

     

      // 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);      // Power is accurate to 10mW

     

      // 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, average them and convert to result

      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

      }

    }

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Andrew J
    Andrew J over 4 years ago in reply to three-phase

    Glad you're following on - I'm finding it really interesting just because I'm way out of my comfort zone!  All I have to do is get this temperature measurement sorted out!

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • three-phase
    three-phase over 4 years ago

    This is a very interesting series to follow along with, I look forward to seeing you complete the project.

     

    Kind regards.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2023 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube