My Pi Description

My Experiences With the Raspberry Pi -- Tracking My Learning -- My Pi Projects

Sunday, August 28, 2016

ATmega328P and the Serial Peripheral Interface

Introduction

This post continues my discussion of register programming of the ATmega328P microcontroller. Specifically, the ATmega's Serial Peripheral Interface, commonly just called SPI. It also continues the discussion of my large LED display from my last blog post.

My Display

I have a five row by ninety column LED display. What would be the best way to deal with the content I wish to display? I could hard code the message in a variable. That's fine if I don't ever want to change the message. I also run into the 2 kbytes SRAM memory limitation of the ATmega328P. I have several different messages to display and would like to add, delete, and edit messages. I also display dynamic messages like the ever changing weather. In fact, if you look at my last post you see I display the current weather and weather forecasts from Weather Underground. I get weather updates every 10 minutes. I don't need to update any more often, and there is a limit to the number of accesses I can make without incurring a charge. Therefore, I need to continuously display the same information until I get an update. The best way to handle all of these issues is to store all messages in another memory device - a nonvolatile memory, of course.
My nonvolatile memory is a 25AA512 serial EEPROM. This eight pin IC contains 64 kilobytes of memory and has builtin SPI. This is perfect, both the serial EEPROM and the ATmega328P have SPI. The Arduino IDE comes with an SPI library that looks pretty comprehensive. But, I just feel more comfortable programming the applicable ATmega328P registers. I have more confidence that I can successfully get the two devices talking to each other. Besides, the Arduino library has limitations.
You can see the serial EEPROM sitting to the right if the ATmega328P on my interface board. Look towards the bottom of my last post.

The SPI

The SPI, or Serial Peripheral Interface is really quite simple. It's not good for long distances but can be reasonably fast. It always involves one master device and one or more slave devices. The master is in complete control. The slaves do not start a conversation, which is just fine when the slave is a serial EEPROM. The master talks to only one slave at a time.
There are four signal lines:
  • SCK, for Serial clock
  • MISO, for Master In, Slave Out
  • MOSI, for Master out, Slave in
  • SS, for Slave Select
The master and all slaves connect to SCK, MISO, and MOSI. However, each slave must receive its own SS connection from the master.
The master contains a clock generator, a shift register, and control circuitry. Each slave has its own shift register. The slave, if it sees its SS line active, uses the clock from the master (SCK) to shift out the data in its shift register onto MISO. At the same time, it shifts in data from the master, on MOSI, into the same shift register. If it does not find SS active it keep its MISO in a high impedance state, allowing other slaves access to MISO.
When the master wishes to write to, or read from, a slave, it brings that particular slave's slave select (SS) line to a logic low. The master will send eight clock pulses to its shift register to shift out the byte of data that was previously stored in its shift register. Each bit appears on MOSI. As each bit is clocked out on MOSI, a bit is simultaneously clocked in from the active slave on MISO.
On the slave side, SS low, allows the SCK clock from the master to be passed to the slave's shift register and takes the shift register output out of a tristate (or open drain). Each clock pulse, clocks out the contents of the slave shift register onto MISO, while clocking data in from the master on MOSI. When the data transfer is complete, the master brings SS high again.
It is possible for multiple bytes to be transferred while SS is low. The clock runs for eight pulses, the shift register is loaded with a new byte and the clock runs for eight cycles again. This is repeated until the entire message is sent or received. The transfer is completed by bring SS high.

SPI Options

There is flexibility built into the SPI. The designer of a device can choose how it's implemented. As stated before, data will be sampled (clocked in), and outputted (clocked out), simultaneously on both MOSI and MISO. The two operations will be done on opposite edges of SCK. The designer can choose to output on the rising edge and sample on the falling edge, or output on the falling edge and sample on the rising edge. The master and slaves must use the same selection.
In SPI parlance, this is controlled by two parameters (not part of the specification, but most manufactures comply with these definitions), CPOL, and CPHA. As follows:
  • CPOL: Polarity of the clock when in an idle state. CPOL = 0, if SCK is low at idle. CPOL = 1, if SCK is high at idle
  • CPHA: Cock Phase. CPHA = 0, if data is sampled on the rising edge of the clock and output on the falling edge of the clock. CPHA = 1 if data is sampled on the falling edge of the clock and output on the rising edge of the clock.
The combination of the clock polarity at idle and the edge to sample and clock out comprises four modes (most manufacturers comply with this):
  • MODE 0: CPOL = 0, CPHA = 0
  • MODE 1: CPOL = 0, CPHA = 1
  • MODE 2: CPOL = 1, CPHA = 0
  • MODE 3: CPOL = 1, CPHA = 1
A diagram is in order:
SPI Modes
Notice that as soon as SS goes low, a bit, either the MSB or the LSB of the master's shift register, and the selected slave's shift register, will appear on MOSI, and MISO respectively. With CPHA = 0, that bit will be the first bit of the requested data. With CPHA = 1, the first bit of requested data does not appear until the first clock transition.
Another Option: Notice in the diagram the bit names like "BIT 0 or 7". Another option the user has is to determine how the bits are shifted out - either LSB (BIT 0) first or MSB (BIT 7) first.
Another option available to the user may be the selection of the clock frequency.

SPI Implementation Using the ATmega328P and the Serial EEPROM

Serial EEPROM Requirements

The 25AA512's SPI bus has definite requirements. You could say that the ATmega328P master is a slave to the slave's requirements. Therefore, the place to start is with the 25AA512's data sheet, as seen here.
The first thing that jumps out at you is that the data sheet does not use the expected pin nomenclature. While they use SCK, there is no MOSI, MISO, or SS. How then do you know that the thing has an SPI? It tell you so. On the first page under "Description" is says, "The memory is accessed via a simple Serial Peripheral Interface (SPI) compatible serial bus.". That's pretty definitive. Their pin definition is as follows: SCK is SCK, MOSI is SI (slave in), MISO is SO (slave out), and SS is CS (chip select).
You don't see the terms CPOL, CPHA, or MODE 0, MODE 1, MODE 2, or MODE 3. This means you have to figure it out for yourself. Luckily, it's obvious. On page 8, Figure 2-1, you see that the clock, SCK, is low when idle, therefore CPOL is 0. The data bits on SI and SO line up with the falling edge of SCK, therefore CPHA is also 0. This equates to Mode 0. The figure also tells you that the most significant bit is available first on SO, and it expects the most significant bit first from the master on SI.
To see the maximum clock speed, you need to look at the AC characteristics and the timing diagrams. The maximum clock frequency is 20 MHz with a VCC of 5V.
There is a lot more information in the data sheet you need to know. For every operation (read, write, erase), there is an instruction that must first be sent to the device. See Table 2-1. Every operation you can do is detailed in the data sheet. You also learn that you can read and write multiple bytes before bringing SS high. However, when writing data you can not cross over to another page when writing multiple bytes.

Programming the ATmega328P

Here is a fragment of code taken from several sketches and distilled down to only reference communicating with the serial EEPROM by the SPI. Here is a link to all the Arduino sketches I wrote for the display.
The sketch only includes some #defines and functions. Looking at the function, initializeSPI(), there is a great deal of information in the comments. You can see the ATmega pin assignments on port B used for SPI. To use the built-in SPI of the ATmega328P, SCK, MISO, and MOSI must use the pins as stipulated in the comments. SS does not necessarily have to be on PB2 if the ATmega is the master. If the ATmega is the slave, then SS must be on PB2. In our case, the ATmega is the master.
There are #defines at the top. The ones under "Serial EEPROM Instructions" come directly from the 25AA512 data sheet, table 2-1 on page 7. SLAVE_SELECT definition relates to the pin on port B, pin PB2 which is the SS pin. .
There are three registers within the ATmega328P related to SPI. See section 23.5 of the ATmega328P data sheet for details of each register:
  • SPCR: SPI Control Register
  • SPSR: SPI Status Register
  • SPDR: SPI Data Register
The comments, "Setting the Control Register, SPCR" shows the choices I made for my project. Notice bits 0, and 1 set SCK frequency to 4MHz.
SPDR is the register that holds the data. Basically, SPDR acts as the shift register. SPSR is the status register. We are only interested in one bit of SPSR, the SPIF bit. This is the SPI interrupt flag. When the transfer of a byte is complete (eight clocks), this bit is set. If enabled (not so in my project), an interrupt will also occur.
The operation of transferring a byte over SPI is contained in my function "SPIoperation()". This function is used for both sending data to the serial EEPROM and reading from the serial EEPROM, Loading a byte of data into SPDR starts the data transfer process. Even if our intention is to read data, we must send send a byte of data. Next, we simply poll SPSR looking for SPIF to be set. When that occurs, we can simply read SPDR to see what was returned from the serial EEPROM. Pretty simple.
The last function "readFromSerialEEPROM()" shows the read process. We send it an address (16 bits) of the location in the serial EEPROM containing the first byte of data we wish to read. We also send it the number of bytes we want to read. We set SS low to start things off. We then write three bytes to the serial EEPROM ignoring what is returned. The first byte is the "READ" instruction. The next two bytes are the upper and lower bytes of the address. After that we simply send something the serial EEPROM will ignore (0xFF) and read a byte from the serial EEPROM. Every time we send 0xFF, the serial EEPROM will increment its address counter and send back a new byte. After reading the number of bytes requested, we bring SS high.
Writing to the serial EEPROM is similar but a little more involved. Note the function "writeToSerialEEPROM(). We send this what we want to store in the serial EEPROM as a String object (my choice here. You can also send it an array of characters). We also send it the number of bytes to store and the starting address in the serial EEPROM. Firs,t we must convert the String to an array of characters.
The memory of the 25AA512 is organized into 128 byte pages. You can write into consecutive addresses, like you can read from consecutive addresses, as is done in my read function. However, unlike a read, you can not cross a page boundary when you write. Taking an example, if you wish to write 129 bytes starting at byte 0, by taking advantage of the consecutive write feature, the 129th byte will not go into address 128, it will go into address 0, overwriting what you put there first.
The write process also starts by bringing SS low. We follow that by write four bytes to the serial EEPROM, WREN (write enable), WRITE, and the upper and lower bytes of the starting address. Next, we can write consecutive bytes, but we have to monitor the address we are going to write to. If that address is a multiple of 128 we are at the page boundary. In that case we must bring SS high, bring SS low, send WREN, WRITE, and the new address, before writing more bytes of data. When you have written the last byte, SS can be brought high again.

Monday, August 1, 2016

ESP8266 - Downloading Weather To LED Display

Introduction

My electronic endeavors, lately, have taken me down two paths. One path was dealing with a salvaged LED display, and the other was the ESP8266. Those paths have now been joined in a challenging project.
Here is a video of the project:

All Design Documentation

All of my design files including schematics, board layout, and all programming sketches are on my GitHub repository. There is an extensive readme file with plenty if details.

The Display

Sometime ago a friend gave me a board with 18 five column by seven row LED matrices, Thanks Mike.
The board was missing the four most critical ICs, namely the microprocessor and two RAM chips. I'm guessing the forth IC was a programmable read only memory used to translate ASCII characters to row and column bit patterns - a character generator.
I probably would have removed those ICs anyway.
Fortunately, I had enough information to reverse engineer the display PCB and was able to design an interface board using an ATmega328P microprocessor. The ATmega device has enough internal SRAM and an internal EEPROM. I built my character generator in the EEPROM. You can see that interface board and its connections to the display PCB as the still shot for the video.
There are 90 columns and the most typical programming scheme would be to start at one end, load the column data for one column, turn that column on, then move down the line doing the same for each column. Each individual LED would be accessed 1/90 of the time. This display PCB divided the columns into six zones. The data for six columns are loaded and all six columns turned on simultaneously. An individual LED is accessed 1/15 of the time. If an LED is meant to be on, it will be six times brighter.
I wrote Arduino sketch for the user to write messages to a serial EEPROM on my interface board, and select one of 28 possible messages stored in the EEPROM to display. I wrote separate sketches to display in four direction:
  • from right to left which I call my Times Square Scroll
  • from left to right. Challenge here was that the letters in each word had to be reversed, otherwise "the" would become "eht"
  • from top to bottom. My favorite. Challenge was to not split up words between lines. See second video in my youtobe video, above.
  • from bottom to top. Like top to bottom with the same challenge
I wanted the display to do more, to be dynamic, to display stuff I did not write - like the weather or latest news.

ESP8266

At the same time, while working on the display, I got on the ESP8266 bandwagon. One of the limitations of the Arduino platform was realistic WiFi access. There Arduino are shields like the Xbee series of boards, but they are pretty expensive.
Along came a tiny 8 pin PCB from China:
This device is a little less than an inch long and a little over one half inch wide. I have seen it being sold for $2.40 USD. The small 32 pin IC is the ESP8266 chip itself. It contains a very capable microcontroller along with the WiFi circuitry - everything but the antenna. The antenna is those wavy lines at the top of the board. I happened to come across a YouTube video from electronupdate where the ESP8266 was photomicrographed. Here is what it looks like inside.
All the red is the logic circuitry for the microcontroller. All the rest is for the Wi-Fi. You can recognize inductors in the picture - those oval items. The eight pin device is a 8 Mbit serial Flash Memory with an SPI.
Although this module is commonly called an ESP8266, its proper name is the ESP-1. It has a couple of limitations. There is only one useful I/O pin and it's not RFI shielded. The pins do have a 0.1" pitch which is nice for mounting on vectorboards.
There are newer generations using the same ESP8266 integrated circuit. The latest seems to be the ESP-14, but the most common seems to be the ESP-12, of which the ESP-12f is the latest flavor. I'm familiar with the ESP-12e, so will not talk about the ESP-14 (same WiFi as in ESP8266 but another microcontroller). the advantages of the ESP-12 are seven fully useful I/O pins, and FCC certified RFI shielding. It does have 2mm pitch castellated pads though. While designed for surface mount placement, I have been able to solder 24AWG solid wire through the holes to connect to other circuitry. I have seen a price of $2.50 USD for the ESP-12e. I'm still going to use the term ESP8266 for all the members of the family.

What's the Big Deal With the ESP8266

Besides the price, this little device can act as a TCP/IP or UDP server or client. It can connect to your WiFi router, and, as a server, contains its own access point. It's often called the "Internet of Things" device.
I have used it as a client where the server is a Raspberry Pi. I employed two in a remote control project, one as a client, the other a server. I utilized the access point in the server device so it does not need my my WiFi router. The access point has an SSID and a password you choose.
If you do a search on the ESP8266, and search YouTube videos, most often you find projects involving the internet. And, indeed, my weather project uses the ESP8266 as a client to get the weather from weatherunderground.com. Other common projects fall into the "internet of Things" category. I have not explored this, myself.
"Internet of Things" projects use the ESP8266 as a server. It's connected to some device you wish to control - your front door electronic lock, for example. You call up the ESP8266's IP address on your browser from anywhere in the world. Let's say you wrote a little javascript in your ESP8266's program to create "Lock" and "Unlock" buttons. These appear in your browser window. Push a button and control your lock. Next project, perhaps (though not control my front door lock).
One of the best things about the ESP8266 is how you program it. There are several options including issuing AP commands and using the Lua interpretive language. I'm not going to discuss those but will talk about what I use - writing C code within the Arduino IDE. I've been using the Ardino IDE for quite some time, writing Arduino sketches. My LED display uses the same microcontroller as used on the Arduino Uno, and I use the Arduino IDE to write all the firmware to control the display.
Two wonderful things happened. The Arduino IDE was opened up to other devices, and the people at NodeMCU provided the functionality for writing ESP8266 firmware using the Arduino IDE. I now had one platform for writing code to both the ATmega328P and my ESP8266. Many of the same libraries as used for Arduino devices were adapted for use on the ESP8266. NodeMCU adapted the existing Arduino WiFi shield library to become the ESP8266WiFi library.

Putting the ESP8266 together With My Display

Here is my interface board that connects to the rear of my display
Above is the layout of the breadboard PCB that controls my display - my interface board. Until recently, there was nothing to the right of the serial EEPROM. The ESP8266 came later. My ESP8266, the ESP-12e version, exists on a development module designed by NodeMCU. It's $8.79 USD from Amazon. Bit more expensive but adds an USB to serial chip for programming, a voltage regulator (5V to 3.3V) and fits nicely on the breadboard PCB having pins on a 0.1" pitch. It's worth every penny. The TXB0104, between the serial EEPROM and the ESP8266 translateS voltage levels of two signals between the ATmega328P, operating at 5V, and the ESP8266, operating at 3.3V.
I'm not going to go into a lot of detail here. The readme file on GitHub explains a lot, and the sketches have lots of comments. I will say that the ESP8266 connects to the weatherunderground api every 10 minutes. It retrieves two .JSON files - one with the current weather conditions and the other, eight forecasts. It signals the ATmega328P via an interrupt that new data is ready. In the meantime, the ATmega328P is reading the weather data from the serial EEPROM and writing it to the display. I functionally divided the serial EEPROM's 64K memory into 2 kbyte blocks. The first 28 of these blocks are for static messages I write that I wish to display. The weather data sits in the next 2 kbyte space. Once the ATmega328P has written all the weather data to the display, it looks to see if the ESP8266 has sent the interrupt. If, not, it simply repeats the same weather information. If the interrupt occurred, the ARmega328P and the ESP8266 talk to each other using a pseudo SPI handshaking scheme that sends the new data to the ATmega328P. The data in the .JSON file is parsed for the desired information, and along with other text, is written to the serial EEPROM.