Raspberry Pi Zero W, GPIO and a Variable Resistor

I know – I really should post a lot more stuff here.

I am hoping that a fresh start will help me get into better habits!

Apart from being a while since I last posted anything, I also have been really busy in the real world and have stagnated a little on the hobby electronics side. I did a project yesterday, just to get me started again. In preparation for another project, I decided to figure out how to process analog input (variable voltage in this case) using the excellent Raspberry Pi Zero W.

It was a very frustrating reboot for me and had to make many mistakes once again. But all worked out in the end, without me destroying the Pi, so I’m happy and here is a summary of what I did, te mistakes I made and the lessons I learned.

Parts List

IMG_0528

poc_bb

Basics:

  • Raspberry Pi Zero W
  • MCP3008
  • Variable Resistor or Potentiometer (I used a 100k Ohm 10% 1/2 Watt 1 Turn 2.77mm Pin Through Hole)
  • Breadboard
  • Assorted wires

Getting Started

At this point I am assuming the reader knows how to get started with a Raspberry Pi.

After googling a bit, I started reading this thread. In a nutshell, I figured I needed a MCP3008. I also followed the rabbit hole via Adafruit to this article. If you visit that page you will notice a banner right at the top directing you to a more up to date article.

I read up a lot on CircuitPython as well. However, by the end I came to the conclusion that the although the CircuitPython project is extremely interesting, it loks like there is also a lot of additional bloat that will be packaged with it and since the Raspbian distro already ships with Python I looked for something more “old school” and simpler. I finaly went with the excellent gpiozero project. More specifically, I was looking at their potentiometer instructions. I decided to just ignore the whole LED thing, and rather just concentrate on getting a reading from the potentiometer as that was my goal.

Mistakes were made…

Adding a header to the Pi Zero

Some time ago I bought an assortment of headers, exactly for situations like I was in now, where I had a Pi Zero without a header. So, at first I soldered only the required number of loose header pins to the Pi, but discovered afterwards they were too small and my jumper wires did not make proper contact. I had to de-solder the individual pins and then ended up just installing a proper female header. For me, that meant about an hour wasted.

Lesson learned: The devil is in the detail. Don’t just assume – check! Anything hardware related have physical characteristics and until I have a more honed level of experience, I need to pay more attention to the details upfront.

Reading the diagrams help!

It is at this point that I made my first mistake that would take me several hours to figure out – and when I saw my mistake, it was one of those “how on earth did I miss that” moments. So, what I did was starting to prepare my set-up to the Adafruit schematic.

The problem is that with the gpiozero instructions, there is just one wire that is plugged into a different pin on the Pi – and I did not realize that until eventually comparing the diagram wire-by-wire – and by accident really – using now the gpiozero schematic.

Lesson learned: Ensure you follow the instructions from the same source from beginning to end. If you jump between source material, pay attention to the little differences, especially wiring – it matters!

Final Outcome

Below is a sample run where you can see the values and how the values change as I play with the potentiometer.

pi@raspberrypi:~ $ python3
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from gpiozero import MCP3008
>>> pot = MCP3008(channel=0)
>>> import time
>>> while True:
...     print(pot.value)
...     time.sleep(1.0)
...
0.5300439667806547
0.5300439667806547
0.5300439667806547
0.5310210063507572
0.5300439667806547
0.5300439667806547
0.5300439667806547
0.5300439667806547
0.5300439667806547
0.6013678553981436
0.6023448949682462
0.6560820713238886
0.6844162188568637
0.6844162188568637
0.6853932584269662
0.47142159257449934
0.45481191988275516
0.39423546653639474
0.3610161211529066
0.3610161211529066
0.36199316072300936
0.3639472398632144
0.36199316072300936
0.36199316072300936
0.36199316072300936
0.3610161211529066
0.3659013190034197

All’s well that ends well, as they say.

Other useful stuff I stumbled upon

Another script/command you can try to read the input values is shown below:

pi@raspberrypi:~ $ pigs spix 0 1 128 0
3 0 1 132
pi@raspberrypi:~ $ pigs spix 0 1 128 0
3 0 1 132
pi@raspberrypi:~ $ pigs spix 0 1 128 0
3 0 2 143
pi@raspberrypi:~ $ pigs spix 0 1 128 0
3 0 3 69
pi@raspberrypi:~ $ pigs spix 0 1 128 0
3 0 1 109
pi@raspberrypi:~ $ pigs spix 0 1 128 0
3 0 1 255

Then, I also discovered this very handy command on the Pi to get the Pi’s pin-out:

pinout-pi-zero

In Conclusion

And that’s a wrap. From here I want to implement a energy monitor – will update once that project is done.

Raspberry Pi Zero W, GPIO and a Variable Resistor

Connecting to your Arduino’s Serial Port

If you connect to your Arduino via USB, you can also connect to the serial port. For me, this worked easiest with the cu command. The quick step-by-step demo below was tested on Ubuntu 16.04LTS on 28 December 2016.

Preparation

Ensure cu is installed. If not, it’s as easy as:

$ sudo apt install cu

After the software is installed, you need to know what to connect to. The information can be obtained in several ways, and below is how I extracted the required information from syslog.

Start with the USB cable disconnected from the PC. Then run the following command:

$ sudo tail -f /var/log/syslog

Now, plug in the cable and you should see something like this:

Dec 28 10:00:31 pc-id kernel: [64803.901164] usb 2-1.4.2: new full-speed USB device number 8 using ehci-pci
Dec 28 10:00:31 pc-id kernel: [64803.998140] usb 2-1.4.2: New USB device found, idVendor=2341, idProduct=0043
Dec 28 10:00:31 pc-id: [64803.998149] usb 2-1.4.2: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Dec 28 10:00:31 pc-id kernel: [64803.998155] usb 2-1.4.2: Manufacturer: Arduino (www.arduino.cc)
Dec 28 10:00:31 pc-id kernel: [64803.998158] usb 2-1.4.2: SerialNumber: 85332343332351F0F120
Dec 28 10:00:31 pc-id kernel: [64803.998820] cdc_acm 2-1.4.2:1.0: ttyACM3: USB ACM device
Dec 28 10:00:31 pc-id mtp-probe: checking bus 2, device 8: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4.2"
Dec 28 10:00:31 pc-id mtp-probe: bus: 2, device: 8 was not an MTP device

Notice the highlighted text. This is the device you need to connect to.

Connecting

Now, you simply connect to the serial port with the following command:

$ cu -l /dev/ttyACM3 -s 9600

To disconnect, type ~. and <ENTER>

And that is it! Simple!

Connecting to your Arduino’s Serial Port

First “Actual” Circuit

Introduction

Wow, I finally got to the point to build my own circuit. For most people, it might sound really silly to start with something as simple as a Voltage Divider. Well, that is how I learn. I wanted to meat a number of objectives with this exercise:

  • Really understand the basics of resistors, volts and all “that basic stuff”
  • Play with my Oscilloscope – the Rigol DS1102D. I picked up this scope for “half” the list price from a pro who bought it, used it less than a dozen times and then his employer bought him a more professional unit, so he no longer needed this “entry level” scope. I have still very little experience or knowledge on these things, but you have to start somewhere, right??
  • Do some actual measurements and compare with the calculated values. Try to understand the differences between calculated and observed values.
  • Learn the “Fritzing” package. I downloaded and tried Eagle, but was soon intimidated by it. I am just not yet on that level. The Fritzing application has some frustrations for me, but it is still in BETA, so I tried to just get the basics done.
  • Go from breadboard to circuit board (not PCB yet – just single sided strip board for now)

It should be important to note that up to now all my projects were breadboard based with only two other PCB type “kit” circuits I assembled. So, I never had to go into any “design” stuff really – just copy what I see in the relevant tutorial I’m following – sometimes with minor tweaks, like combining two circuits into one.

The whole process, going from schematic to breadboard to circuit board, was really fun. If I could begin my career path over, this would be it!

The Basics

I can really recommend Sparkfun’s Learning site, which provided me with some good background reading, along with the normal Wikipedia and other sources. The specific site I used for background reading for this product was:

From the “theory” I went from their schematics to my own breadboard implementation.

circuit_2016-02-14_bb

I must admit, I first worked on the breadboard before going to Fritzing – it really should have been the other way around…

At this stage, I connected  the “battery” end to the variable voltage regulator of the Yihua 853D. I did the initial measurements on the Rigol.

IMG_0286

Channel 1 was measuring the 5V DC from the Yihua and on the divider I measured 1.26 V average. Not exactly the 1.2406 V as calculated!

The Build

So, I built the circuit on a tiny piece of strip board:

First of all, the board is tiny – about the size of my thump nail. This presented some challenges for me:

  • I didn’t realize before that I have a little “shake” in my hand. Was it just nervousness?
  • I need to get my eyes tested! I really find it hard to see properly and I realize that the components on more modern boards are much smaller!

But, it all worked in the end. Total build time for me was about 30 minutes, including the cutting of the board from the larger board I bought.

The Measurements

Below is my data. I didn’t use the Rigol again to measure the output voltages, but the UNI-T UT30C Multi Meter.

My measurements:

Measurement #   V1      V2
-----------------------------
        1       3.3     0.83    
        2       5.0     1.25    
        3       6.0     1.49    
        4       9.0     2.21
        5       12.0    2.99
        6       15.3    3.72

Chart

measurements
Conclusions

This was a fun experience. I discovered some areas where I need to develop a little more. I still need to tie some loose ends, especially in explaining the differences between the calculated values and the measured values. I think I can answer he why, but I want to make sure I understand exactly what is going on.

Well – until the next time then!

First “Actual” Circuit

First Arduino I2C Experience

Background

So this is the first steps I’m taking toward a “big project”. The idea is to build a controller unit with sensors attached as individual units from which data will be collected and send to a cloud service for storage and presentation – ala IoT.

The bigger project will be discussed in a later post, but for now I am sharing my initial experiment with some notes (and questions… many questions).

Design Notes

This proof of concept project aims to explore I2C between two Arduino UNO’s to see if this is a viable approach to what I want to do. The idea eventually would be to have many “sensors” on a I2C bus providing the master with data on request.

Products Used

Below are some products I used.

Apart from the Open Source software stack, I did spend a lot of money – in my opinion – in obtaining what I required. However, I feel it was money well spent as I am using the equipment for a lot of other experiments and learning activities as well.

Reference Sites

Below are some sites I referenced to put the solution together.

Twitter links

To follow any of the guys I reference on Twitter, please have a look at their pages below:

Of course, my twitter page is at https://twitter.com/nicocoetzee1 🙂

Solution Overview – In Pictures

I have not managed to go into this whole diagramming or fritzing thing, so I am afraid you have to rely on my photos for now. I think this is one of the next skills I need to acquire!

Complete Set-up

2015-10-18 12.05.00

This image shows the SparkFun Redboard acting as the Master and with the LCD attached.

The basic set-up exactly mimics project 15 of the SparkFun Inventors Kit. You can download the PDF manual from their site. I have the version 3.1 kit, but the version 3.2 kit in the download is also still good.

Output on the LCD

20151018_120707

The LCD is updated every second with a new value it obtains from the slave “sensor” – although the slave only produces a random number between 0 and 1024 at the moment.

The idea is to now add a WiFi module in order to send this data to the cloud. Later, the random number generator will be replaced with some more useful sensor, like a temperature sensor. Finally I hope to hookup a whole bunch of sensors.

USB Connectivity

20151018_120800

I use a 8 port powered USB hub I got from a local computer dealer. Linux and USB can have it’s share of issues, but sometimes you take a change and in this case I think I got lucky!

I will go into more detail as to how to identify and address your devices a little further on in this article.

BitScope UI

I will be the first to admit that I no very little at this point about logic analyzers, but this is part of the learning path that I am on. At the moment, I have no idea really how to go into the analysis of what I see, but I was able to dump the readings to a CSV. I am sure that in time to come I will be able to make much better use of this piece of equipment.

I also have a proper hardware Oscilloscope and Logic Analyzer: the Rigol DS1102D – I will also be using this from time to time. I argued that it’s cheaper to blow up the BitScope than the Rigol, hence me sticking with the BitScope for now.

Sketches

Let me start to say that I have not tried to be efficient or neat with any of the sketches yet – I just want something that works at the moment. I am also still struggling to wrap my head around debugging strategies, so my thinking is to dump debug output to the serial interface from where I can monitor all the devices. This may not be the best approach for “production” solutions, but I am still thinking about long term strategies for debugging and perhaps even remote diagnostics.

From a project point of view, here is my project directory layout:

nicc777@electrostatic:~/PlatformIO_Projects/I2C_Test01$ tree
.
|-- Master
|   |-- lib
|   |   `-- readme.txt
|   |-- platformio.ini
|   `-- src
|       `-- maim.cpp
|-- Master_Sender_bb.png
|-- README
|-- Slave
|   |-- lib
|   |   `-- readme.txt
|   |-- platformio.ini
|   `-- src
|       `-- maim.cpp
`-- Webpage-Dumps

The “Webpage-Dump” directory is where I collected my info from the web for future reference – you never know how long these resources will remain on the web.

The Master Node

Content of “Master/src/maim.cpp” (note: “maim” is actually a typo, but that’s life happening for you).

#ifdef ENERGIA
  #include "Energia.h"
#else
  #include "Arduino.h"
#endif

#ifndef LED_PIN
  // Most Arduino boards already have a LED attached to pin 13 on the board itself
  #define LED_PIN 13
#endif

#include 
#include 

// Initialize the library with the pins we're using.
// (Note that you can use different pins if needed.)
// See http://arduino.cc/en/Reference/LiquidCrystal
// for more information:

const byte SLAVE_ADDRESS = 8;

LiquidCrystal lcd(12,11,5,4,3,2);
bool gotData;
int dataValue;
char dataValueStr[] = {' ', ' ', ' ', ' ', ' ', ' '};
int cPos;
int loopcount;

void clearLCDStatus()
{
  lcd.setCursor(0,1);
  lcd.print("              "); // Erase the largest possible number
}

void setup()
{
  loopcount = 0;
  // Init the LED and switch it off
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("Value:");
  Wire.begin ();
  delay(10000);
}

void resetValues()
{
  cPos = 0;
  dataValue = -1;
  gotData = false;
  for(int i=0; i<6; i++){     dataValueStr[i] = ' ';   } } void loop() {   loopcount = loopcount + 1;   Serial.print("Loop nr: ");   Serial.println(loopcount);      gotData = false;   clearLCDStatus();   lcd.setCursor(0,1);   lcd.print("-- no data --");   Serial.print("   About to send request for data... ");   //Wire.beginTransmission (SLAVE_ADDRESS);   Wire.requestFrom(SLAVE_ADDRESS, 4);   Serial.println("DONE. Waiting for data...");   Serial.println("");   delay(50);   while (Wire.available()) { // slave may send less than requested     char c = Wire.read(); // receive a byte as character     delay(50);     Serial.print("From slave: ");     Serial.println(c);     //Serial.print(c);         // print the character     dataValueStr[cPos] = c;     cPos = cPos + 1;   }   Serial.println("");   Serial.print("cPos=");   Serial.println(cPos);   Serial.println("");   if(cPos > 0){
    cPos = 0;
    gotData = true;
  }

  if( gotData ) {
    clearLCDStatus();
    lcd.setCursor(0,1);
    lcd.print(dataValueStr);
    Serial.print("   Value: ");
    Serial.println(dataValueStr);
  } else {
    clearLCDStatus();
    lcd.setCursor(0,1);
    lcd.print("-- no data --");
    Serial.print("   Value: ");
    Serial.println("-- no data --");
  }
  
  resetValues();
  delay(900);

}

This sketch is UGLY – I know!! But it get’s the job done, and I get plenty of debug information on the serial interface.

The Slave Node

Content of “Slave/src/maim.cpp”:

#ifdef ENERGIA
  #include "Energia.h"
#else
  #include "Arduino.h"
#endif

#ifndef LED_PIN
  // Most Arduino boards already have a LED attached to pin 13 on the board itself
  #define LED_PIN 13
#endif

// Example based on advice from http://gammon.com.au/i2c and https://www.arduino.cc/en/Tutorial/MasterReader

#include 

int randNumber;
int seconds;
long tCounter;
int incomingByte;
char spaceChar = ' ';

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  randNumber = random(1024);    // Simulate a reading from some sensor...
  char responseText[] = "";
  sprintf(responseText, "%d", randNumber);
  if(randNumber < 10){
    responseText[1] = spaceChar;
    responseText[2] = spaceChar;
    responseText[3] = spaceChar;
  } else if(randNumber < 100) {
    responseText[2] = spaceChar;
    responseText[3] = spaceChar;
  } else if(randNumber < 100) {     responseText[3] = spaceChar;   }   Wire.write(responseText); } void setup() {   Serial.begin(9600);   seconds = 0;   tCounter = 0.0;   incomingByte = 0;   randNumber = 5;   // Init the LED and switch it off   pinMode(LED_PIN, OUTPUT);   digitalWrite(LED_PIN, LOW);   Wire.begin(8);                // join i2c bus with address #8   Wire.onRequest(requestEvent); // register event } void loop() {   delay(100);   tCounter = tCounter + 100;   if( tCounter >= 1000 ) {
    seconds = seconds + 1;
    tCounter = 0.0;
  }

  // Serial Diagnostics: send data only when you receive data:
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();
  
    // Diagnostics to Serial...
    Serial.print(seconds);
    Serial.print(" ");
    Serial.println(randNumber);
  }

}

Note: The loop() function could be left empty, but I decided to dump all my debug stuff here – again dumping to the serial console.

Working with PlatformIO

Sketches and Multiple Boards

Well, I absolutely love this development platform! I just could never get used to the Arduino IDE for some reason – perhaps to do with my development background which has rarely involved IDE’s. With PlatformIO I do my coding in Vim and use the familiar command line environment on Linux. Although I have not don’t it for this project, you could easily add version control like Git for your project. I will probably be using Git for my major project(s).

Working with multiple platforms at the same time is wonderful, but you will need to know how to address the various platforms.

What I did was to insert one device at a time to see how they are identified. There are two tools you can use for this purpose:

  • PlatformIO’s commands
  • Linux commands

For PlatformIO, you can use the following command to identify the USB device(s):

nicc777@electrostatic:~$ platformio serialports list | tail
/dev/ttyUSB0
------------
Hardware ID: USB VID:PID=0403:6001 SNR=A5025X7S
Description: Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC 

/dev/ttyACM0
------------
Hardware ID: USB VID:PID=2341:0043 SNR=85332343332351F0F120
Description: ttyACM0

This is just an example showing the two Arduino’s. By the process of running the command after you plug in each device in turn, I found the following:

  • The BitScope was at /dev/ttyUSB0 (not as per the above – at that stage I removed the BitScope)
  • The Redboard was at /dev/ttyUSB1
  • The Arduino was at /dev/ttyACM0

With the above setup, you can compile and upload a sketch to a specific device using the following command (note: the BitScope was unplugged now, so the Redboard was at /dev/ttyUSB0):

nicc777@electrostatic:~/PlatformIO_Projects/I2C_Test01/Master$ platformio run --target upload --upload-port /dev/ttyUSB0 
[Sun Oct 18 10:01:58 2015] Processing sparkfun_redboard (platform: atmelavr, board: sparkfun_redboard, framework: arduino)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
avr-g++ -o .pioenvs/sparkfun_redboard/src/maim.o -c -fno-exceptions -fno-threadsafe-statics -g -Os -Wall -ffunction-sections -fdata-sections -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO_AVR_UNO -DARDUINO=10605 -DPLATFORMIO=020303 -I.pioenvs/sparkfun_redboard/FrameworkArduino -I.pioenvs/sparkfun_redboard/FrameworkArduinoVariant -I.pioenvs/sparkfun_redboard/Wire -I.pioenvs/sparkfun_redboard/Wire/utility -I.pioenvs/sparkfun_redboard/LiquidCrystal src/maim.cpp
src/maim.cpp: In function 'void loop()':
src/maim.cpp:74:36: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Wire.requestFrom(SLAVE_ADDRESS, 4);
^
In file included from src/maim.cpp:12:0:
.pioenvs/sparkfun_redboard/Wire/Wire.h:59:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int)
uint8_t requestFrom(int, int);
^
.pioenvs/sparkfun_redboard/Wire/Wire.h:57:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t)
uint8_t requestFrom(uint8_t, uint8_t);
^
avr-g++ -o .pioenvs/sparkfun_redboard/firmware.elf -Os -mmcu=atmega328p -Wl,--gc-sections,--relax .pioenvs/sparkfun_redboard/src/maim.o -L.pioenvs/sparkfun_redboard -Wl,--start-group -lm .pioenvs/sparkfun_redboard/libFrameworkArduinoVariant.a .pioenvs/sparkfun_redboard/libFrameworkArduino.a .pioenvs/sparkfun_redboard/libWire.a .pioenvs/sparkfun_redboard/libLiquidCrystal.a -Wl,--end-group
avr-objcopy -O ihex -R .eeprom .pioenvs/sparkfun_redboard/firmware.elf .pioenvs/sparkfun_redboard/firmware.hex
BeforeUpload(["upload"], [".pioenvs/sparkfun_redboard/firmware.hex"])
"/home/nicc777/.platformio/packages/tool-avrdude/avrdude" -v -p atmega328p -C "/home/nicc777/.platformio/packages/tool-avrdude/avrdude.conf" -c arduino -b 115200 -D -P /dev/ttyUSB0 -U flash:w:.pioenvs/sparkfun_redboard/firmware.hex:i

avrdude: Version 6.0.1, compiled on Apr  3 2014 at 21:52:43
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch

System wide configuration file is "/home/nicc777/.platformio/packages/tool-avrdude/avrdude.conf"
User configuration file is "/home/nicc777/.avrduderc"
User configuration file does not exist or is not a regular file, skipping

Using Port                    : /dev/ttyUSB0
Using Programmer              : arduino
Overriding Baud Rate          : 115200
AVR Part                      : ATmega328P
Chip Erase delay              : 9000 us
PAGEL                         : PD7
BS2                           : PC2
RESET disposition             : dedicated
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

Block Poll               Page                       Polled
Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

Programmer Type : Arduino
Description     : Arduino
Hardware Version: 3
Firmware Version: 4.4
Vtarget         : 0.3 V
Varef           : 0.3 V
Oscillator      : 28.800 kHz
SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading input file ".pioenvs/sparkfun_redboard/firmware.hex"
avrdude: writing flash (5432 bytes):

Writing | ################################################## | 100% 0.77s

avrdude: 5432 bytes of flash written
avrdude: verifying flash memory against .pioenvs/sparkfun_redboard/firmware.hex:
avrdude: load data flash data from input file .pioenvs/sparkfun_redboard/firmware.hex:
avrdude: input file .pioenvs/sparkfun_redboard/firmware.hex contains 5432 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.56s

avrdude: verifying ...
avrdude: 5432 bytes of flash verified

avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK (H:00, E:00, L:00)

avrdude done.  Thank you.

Debugging – Using the Serial Console

As with the example above, you can attach to a serial console by addressing the relevant serial device.

First I show an example of connecting to the Master and then the Slave:

nicc777@electrostatic:~/PlatformIO_Projects/I2C_Test01/Master$ platformio serialports monitor -p /dev/ttyUSB1
--- Miniterm on /dev/ttyUSB1: 9600,8,N,1 ---
--- Quit: Ctrl+]  |  Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
Loop nr: 1
   About to send request for data... DONE. Waiting for data...

From slave: 2
From slave: 7
From slave: 6
From slave: 

cPos=4

   Value: 276                
Loop nr: 2
   About to send request for data... DONE. Waiting for data...

From slave: 9
From slave: 3
From slave: 0
From slave: 

cPos=4
nicc777@electrostatic:~$ platformio serialports monitor -p /dev/ttyACM0
--- Miniterm on /dev/ttyACM0: 9600,8,N,1 ---
--- Quit: Ctrl+]  |  Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
2 753
2 753
3 42
4 42

Final Thoughts

I am happy that I eventually got his far. The entire exercise took about 8 hours over two days. I do have some questions though and I will need to investigate these as time goes by.

The I2C Examples

In one of the resources I referred to (http://gammon.com.au/i2c) the hookup diagram shows some resistors being used between the two Arduinos. I have not figured out why that is necessary yet, but I must be honest in that I have not really tried. Perhaps it is mentioned on the page – but I was more interested in the sketches as examples at the time. I still need to get back to this item to understand it better.

I2C Blocking

Although it does not seem to be consistent, I have found that the master especially can block as soon as something funny happens on the I2C interface. For example, when I remove the slave and couple it again, the Master may not always start to read again – it may take another unplug and reconnection for the process to start going again.

I also found that un-hooking the BitScope probes from the I2C connectors caused a similar issue – nit sure yet why. Unplugging the slave and reconnecting it twice resolved the issue.

In future I plan to look at non-blocking options and perhaps RTOS or timeout strategies. I am not yet sure if any of these approaches will work, but I am sure to build viable production products these issues will have to be addressed in some way. Perhaps it even turns out that I2C is not the optimal strategy and I may need to look at other options. I was toying with the idea of using a Raspberry Pi as the Master and then communicate to the Slaves which may all by ESP8266 based.

Other Thoughts

As a long term strategy I would also need to consider times when a network is not available. I have some EEPROM 256k chips lying around, so perhaps I can dump the data in there and then synchronize to the cloud as soon as network connectivity is restored. But will my sketches be able to handle all this logic? Some serious thought needs to go into this.

I also mentioned the diagnostics. Serial diagnostics is fine in a lab environment, but how would I do this for products in the field? I may need to develop some remote command capability and find efficient ways to communicate with the master. Again this drives the case for using a Pi as I can then add a lot more complex code to the mix. It will however raise the price – I can better understand now the real issues engineers have to deal with!

In Conclusion

I hope someone else could find this useful. At the moment I have configured WordPress to close comments after 30 days, so if you need to chat to me about this specific page and you are not able to leave a comment, please see how you can contact me from this page: https://about.me/nico.coetzee

Have fun!

First Arduino I2C Experience

Here we go…

A new journey starts for me. In fact, it has actually started some time ago – maybe 2 years – but I am now at the point where I think I can make some contributions to the larger community.

I have been interested in electronics as far as I can remember back, but never really had an opportunity to develop this interest. That was until about two years ago. I have now the basics of an electronics lab with some components and hobby kits that I have acquired of the last couple of months. I feel I can now start to share what I have learned and what I am still learning.

You are welcome to consider any contributions here as in the public domain. All I ask in return is a link back to either the site or specific story. Please feel free to comment and share your views. I will however remove comments that are not on topic or that are offensive.

Enjoy!

Here we go…