I’m having the best time with Python.  It is a very easy language to use and it’s interpretive nature makes it a dream to prototype with.

The only thing preventing me from using it on the Feather Huzzah to talk to the ATM90 FeatherWings is a SPI library for the ATM90.  But wait, Tisham wrote a SPI library for the Arduino IDE.  How hard can it be to port the library to Circuit Python?

The Goal

The goal of this post is to document the steps I took to convert the ATM90E26 SPI Arduino library to Circuit Python.

Thanks To Those That Went Before

  • Tisham Dhar (company is whatnick) for the ATM90E26 FeatherWing, supporting Arduino Library, his kindness, and his willingness to share knowledge.  This post is all about porting Tisham’s Arduino library to Circuit Python.  Porting was MUCH easier thanks to having the Arduino Library available.  If not the least to see how funky SPI seems to be on the ESP8266.  For example, the Arduino library sets SPI to MODE2 for the Huzzah…when in reality the ATM90e26 speaketh MODE 3.  This is still weird to me…grrrr…but once I figured out a potential “kludge”, I was able to fix my challenges with SPI…although I also got help from my next person I am incredibly thankful to:
  • Scott Shawcroft (aka tannewt)…I’m bumbling around trying to get the SPI gunk to work with Circuit Python.  I go to Adafruit’s Circuit Python Discord Chat…I ask a question that is stumping me.  Scott takes several (several) minutes to help me figure stuff out…and….SHAZAM… the SPI stuff falls into place.  During the debugging process, Scott was incredibly sharp, helpful, and kind.  Which gets me to my next round of thanks..
  • Tony Dicola I learn A LOT from Tony’s tutorials and videos.  The particularly useful tutorial for this post: Porting an Arduino library to CircuitPython: VL6180X Distance Sensor.
  • Adafruit – THANK YOU for the community you have built, the hardware and software that I seem to constantly crave.  I can only hope more companies see you as a role model for how to run a successful, community driven company that focuses on the positive.
THANK YOU THANK YOU THANK YOU THANK YOU THANK YOU THANK YOU…..THANK YOU…..AND MORE THANKS TO YOU…..

Open Source

    • HappyDay_energyic_spi.py : Circuit Python library for the ATM90e26…the protagonist of this post.
    • PyspiTest.py : Lil’ test app.  It imports HappyDay_energyic_spi.py and calls into the functions … like getSysStatus() ….

Stuff I Did

Install Circuit Python on a Feather Huzzah

Here’s what I learned from installing Circuit Python:

1. Use the esptool to erase the Huzzah’s flash and install Circuit Python.  I didn’t have this on my Mac, so from a terminal window…: $ pip install esptool

 Now that I had the tool that knows how to r/w the Huzzah’s flash, I needed to know the serial port the Huzzah was connected to.  From a terminal window….$ ls /dev/cu*

2.  PRACTICE SAFE FLASHING…START BY ERASING.  Sorry for shouting but I wandered down a gnarly pit before I practiced erasure.  By gnarly pit, I changed wifi’s and Circuit Python was NOT happy…Circuit Python would continually loop:

File “inisetup.py”, line 9, in wifi
OSError: can’t set AP config 

 

Adafruit CircuitPython 2.1.0 on 2017-10-17; ESP module with ESP8266
>>> scandone
no <SSID name> found, reconnect after 1s
reconnect

From a terminal window….

$ esptool.py -p /dev/cu.SLAB_USBtoUART erase_flash

3. Get the copy of Circuit Python from  Adafruit’s GitHub location that holds Circuit Python releases.  I renamed the binary to a simpler name (huzzah.bin)

4. Jumper GPIO0 and GND so the ESP826 is in boot mode.

5. From a terminal window…  $ esptool.py -p /dev/cu.SLAB_USBtoUART –baud 460800 write_flash –flash_size=detect 0 huzzah.bin

Check Install

Easiest way I found to check install was to go into REPL: 

$ screen /dev/tty.SLAB_USBtoUART 115200

OKIDOK.  Got the >>>

All is well.

Get ampy Going

Unfortunately, I can’t do a USB mount on the Huzzah.  I ended up using the  ampy tool.  I used this convenient tool to copy my Python library code to the Huzzah as well as run my test app.

Note: I didn’t do this but:

If you don’t want to constantly specify the –port option you can set the AMPY_PORT environment variable in your terminal session and ampy will use it as the board’s serial port.

$ export AMPY_PORT=/dev/tty.SLAB_USBtoUART

Write Python Library

The ATM80e26 Circuit Python library is called HappyDay_energyic_spi.py.  I’m not going to explain the code because not only is it similar to the Arduino library, Python code seems easy to understand.  Beside, you write better Python code than I do.

Resources

$ ampy -p /dev/tty.SLAB_USBtoUART put spi_device.mpy  /lib/spi_device.mpy

(after creating the /lib directory using amp’s mkdir command) 

Note: Library files go in the lib directory because it’s part of the Python path by default.

Adjust the Voltage Gain

THIS IS IMPORTANT.  I discuss adjusting the ATM90c26 voltage gain to a specific setup in this post.

 

Figure out SPI Gobly Gook

By “Gobly Gook” I mean the SPI phase and polarity.  Now I got (ok, perhaps totally) confused on this.  The Arduino library sets the SPI Mode for the Huzzah to Mode 2.  But, the ATM90e26 speaketh in Mode 3.  Grr…

NewImage

From the data sheet (4.1): Data on SDI is shifted into the chip on the rising edge of SCLK while data on SDO is shifted out of the chip on the falling edge ofSCLK.

Bytes from the ATM90e26 Meter Status Register

The Meter Status Register is:

#define EnStatus 0x46 //Metering Status

The SPI section of the data sheet notes (section 4.1.1/Read Sequence) notes the high bit of the MOSI request is set to 1 when asking to read a register.

0x46 | 1 << 7 = 0XC6

Read Meter Status Register Request 

MOSI == SDO (Master Output —> Slave Input) -> Falling Edge: E.g. MOSI byte: 1100 0110 = 0XC6 

ArdspiTestMeterStatusMOSI

Image on Imgur 

Data Returned From ATM90e26 

MISO == SDI (Master Input <— Slave Output)  -> Rising Edge E.g. First MISO byte: 1100 1000 = 0XC8

ArdspiTestMeterStatusMISO

Image on Imgur 

Set up The Init Function

This led me to:

def __init__(self,spi_bus,cs):self._device = SPIDevice(spi_bus,cs,baudrate=200000,polarity=1,phase=1)

I set the baud rate to what the Arduino library had… then there is the polarity=1, phase=1 (i.e.: SPI mode 3).

Figure Out the GPIO Naming

As you can see in the PyspiTest.py test app,  board pins are used to set the CS:

cs = digitalio.DigitalInOut(board.GPIO0)

before creating an energyic_SPI instance.  i.e.:

>>> import board

>>> dir(board)

[‘ADC’, ‘GPIO16’, ‘GPIO14’, ‘SCK’, ‘GPIO12’, ‘MISO’, ‘GPIO13’, ‘MOSI’, ‘GPIO15’, ‘GPIO2’, ‘GPIO0’, ‘GPIO4’, ‘SDA’, ‘RX’, ‘TX’, ‘GPIO5’, ‘SCL’]

Run The Test App

s margaret$ ampy -p /dev/tty.SLAB_USBtoUART run <python test program..>

Here are results that I got without using a CT or power calibration.  It’s the same results I received when I ran the Arduino library:

Checksum 1:4A34
Checksum 2:D294
Sys Status:0
Meter Status:C801
Voltage:0.03
Current:0.01
Active power:0.00
p.f.:0.00

That’s It

ChallengesBringOpportunites  YIPPEE!!! IT WORKS.  Thanks for reading this far.  Please find many things to smile about.