My Pi Description

My Experiences With the Raspberry Pi -- Tracking My Learning -- My Pi Projects
Showing posts with label Arduino IDE. Show all posts
Showing posts with label Arduino IDE. Show all posts

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.

Tuesday, May 13, 2014

Arduino Libraries - DON'T DO THAT!

Don't do what? Well, lets lead up to the answer to that question.
I wrote a fairly long library .cpp file (and, of course its .h file). It worked just fine in my sketch. But, I decided to make some changes. Not wanting to lose what I had (I knew it worked) I made copies of both the .h and .cpp files, appending "save" to the file name for each of the two files. I had four files: something.h, something_save.h, something.cpp, and something_save.cpp. All four files were under home/pi/sketchbook/libraries. I wanted to minimize the changes to my sketch (.ino file). Therefor, I did not want to change any of the function names in the library files. I made my changes, and compiled the sketch. The result: I received a list of compiler errors that went on and on and on.
To illustrate what happened, I repeated the sequence of events with a really small, and trivial example:
The only differences I made were to append a "+ 1" to "c = a + b" in the original .cpp file, just to make something different, and to append "_save" and "_SAVE" to the top lines of the bottom two files. I compiled the sketch and you can see what occured:
That's a lot of error messages for a tiny example sketch. I know it's a little hard to read the error messages because of the red text. Here is what it says:
Mylibraries/ridicules.cpp.o: In function RIDICULES::addNumbers(int, int)':
/home/pi/sketchbook/libraries/Mylibraries/ridicules.cpp:8 multiple definition of RIDICULES::RIDICULES()'
Mylibraries/ridicules_.cpp.o:/home/pi/sketchbook/libraries/Mylibraries/ridicules_save.cpp:8> first defined here
Those three messages are repeated three times. Please note I created a directory under home/pi/sketchbook/libraries called "Mylibraries". I stick my libraries there to separate them from the ones that came pre-installed with the IDE.
Note what I have colored red. This is reference to my ridicules_save.cpp file. My sketch does not reference "ridicules_save". Why is "ridicules_save" part of the build? To start to understand things, I did a search for the object files (".o") referenced in the compiler errors. I knew they were not in the Mylibraries directory. Here is what I found:
Note that all of these object files were created at the same time. They are all created every time you compile.
The IDE generates an object file (with an .o extension) of every .cpp file it finds in Mylibraries. It also makes an object file of .cpp files not in the sketch/libraries path. These ".o" files are needed to support Arduino functionality. There are other .cpp files in the sketch/libraries path that are skipped. This includes, for example, OneWire.cpp. Perhaps these are not included because I have never compiled a sketch using them.
I would have thought the IDE would only make an object file of the .cpp files you call for in your sketch and not all the others in your directory. But it does, so now that we know we can answer that question at the top:
Don't have more than one .cpp file with functions that have the same name in the libraries directory. If you need to keep copies of older versions of library files stick them in a directory outside of /home/pi/sketchbook/libraries.
By the way, you can have two files with addNumber() functions, just not two RIDICULES::addNumbers functions. Make one VERY_RIDICULES::addNumbers and you will be OK.

Sunday, January 19, 2014

Gertboard - Programming With ATmega Registers

Arduino IDE Built-in Functions Vrs. Direct Register Programming

Functionally, what is the difference between this script:
and this script:
Answer: NOTHING
Note: In the sketches discussed here, to see if the LEDs on the Gertboard are ON or OFF, PB0 is connected to BUF1, PB1 to BUF2, PB2 to BUF3, PB3 to BUF4, PB4 to BUF5, and PB5 to BUF6.
Both scripts turn LEDs on the Gertboard ON and OFF. First, LEDs 1, 3, and 5 are ON with 2, 4, and 6 OFF. One second later, 1, 3, and 5 are OFF, and 2, 4, and 6 are ON. One second later, the process repeats itself, on and on. The first script uses functions built into the Arduino IDE. While the second script uses the Arduino IDE delay() function, the LEDs are controlled by writing directly to microcontroller registers. The second script is sure a lot shorter and takes up about half of the space in memory. I must admit that it does use a little trick that I'll discuss later. That trick can not be used with the first script. I tried to shorten the first script by using for loops and if/else statements in lines 12 - 27. I gave up because it didn't seem to save lines of code.
The built-in functions that are part of the Arduino IDE are a convenient way to interface with the ATmega I/O pins. The second script shows another method, and that is to communicate directly with registers within the microcontroller associated with those I/O pins. Registers are eight bit bytes that are addressable within the ATmega memory space. In most cases, each bit of a register can be either read or written to. Each bit, or a combination of bits control some function or produce some effect. Before you can deal with these registers you need knowledge of what the registers do. That knowledge comes from the ATmega datasheet from Atmel.
If you are not concerned about writing a few more lines of code or how many bytes get loaded into the microcontroller, what other reasons would there be for programming ATmegta registers? Here are a few reasons:
  • IT'S EASY TO DO. There is a library include file, iom328p.h for the ATmega328P, that defines all of the registers and register pins in exactly the same way that they are named in the datasheet. For example, in the second sketch, the line "DDRB=0b00111111;" correlates directly to 13.4.3 on page 92 of the datasheet. This is the datadirection register for port B. Writing a 1 to the lower six bit positions makes pins PB0 to PB5 outputs. "PORTB=0b00101010;" correlates to 13.4.2 on page 92. This will make PB1, PB3, and PB5 logic high, turning on their respective LEDs. The first line of that second script, "#include <avr/io.h>" looks to see what ATmega chip you are using and, in our case, the ATmega328P. When the script is compiled, the definitions in iom328p.h are used to figure out the locations within the ATmega to access.
  • There are things you can do that are not supported by the built-in functions. For example, even though you can do PWM to control a motor using analogWrite(), you are stuck with one frequency - about 490Hz. If your motor would rather work at 10khz, you can program the counter registers. There are a lot more things you can do or develop yourself. For instance, I wish to develop my own 1-Wire interface for use with my DS18B20 temperature sensors.
  • I found that the function delayMicroseconds() produces delays that area about 2/3 of the correct values. I noticed this first with my camera remote control project. I was looking for a pulse width of 284usec but had to program delayMicroseconds(415) to get 284usec. Testing with an oscilloscope, from a desired delay of 10 to 3000usec, I consistently measured about 67% of the desired value (the delay() function is pretty accurate). So, I plan to write my own function for microsecond delays. There are two 8 bit counter/timers and a 16 bit counter/timer accessible by registers that can be utilized.
  • For me, I like getting closer to the hardware when programming. It makes me feel more in control.
  • Gives me a chance to use those fun bitwise operators like OR, AND, and EXCLUSIVE OR and shift bigs right and shift bits left.
  • Here are most of the ATmega functions that are accessible through registers:
    • I/O Pins, both content, data direction, and pull-up resistors for inputs
    • The various counter timer registers and prescallers for 8 and 16 bit counter/timers. These also control the PWM oscillator functions at the I/O pins
    • SPI control, status, and data registers
    • Registers for the serial communications using the USARTs
    • Registers for the 2-Wire serial interface
    • Analog comparator
    • A to D converter
    • Interrupts
I said I like to use bitwise operators, and the EXCLUSIVE OR operator is the trick I used to make that second script so short. Line 7 turned three of the six LEDs on (PB1, PB3, and PB5). Line 12 is going to toggle those LEDs that are ON to OFF and those that are OFF to ON.
Line 12 uses a compound operator. Recall that =+ is a compound operator. The expression A =+ 1 is the equivalent to A = A + 1. In our line 12, the compound operator is =^ which is an EXCLUSIVE OR. It is the equivalent of PORTB = PORTB ^ 0b001111. The EXCLUSIVE OR compares two bits. If they are the same (both 0 or both 1) the result is a 0. If they are different, the result is a 1. Let's apply that to PORTB which we will assume is 00101010. Putting one number under the other let's see what we get:
  00101010 PORTB
  00111111 EXCLUSIVE OR with this binary number
  00010101 NEW PORTB value
Let's do that again:
  00010101 PORTB
  00111111 EXCLUSIVE OR with this binary number
  00101010 NEW PORTB value
Note we are back to where we started. I hope you can see that this operation will toggle the six LEDs ON and OFF.

Another Sketch Writing To I/O Pins

I would like to introduce another sketch. This one uses four bitwise operators. Between the two sketches we will have used all of the bitwise operators except for the shift right.
This sketch uses the same six LEDs on the Gertboard except only one LED is lit at any one time. It starts with all LEDs OFF, then lights each LED for one second starting with the LED connected to pin PB0. Each LED, down the line, is ON for one second. One second after PB5 is lit, the sequence starts over again at PB0.
Let's take a look at line 12. Here we have two bitwise operators, an OR compound operator, |=, and a SHIFT LEFT, operator, <<. If you are not familiar with this type of notation it surely looks strange.
Line 12 means we are going to take the current contents of the register PORTB, the register connected to pins PB0 through PB5, and OR them with some value so that PORTB is changed. I'll talk about what OR means in a minute. For now, the question is: what is that value we are going to use to change the contents of PORTB? Why, it is (1 << PORTB0), of course. What?? What does that mean? If you look into the include file, iom328p.h, (called by avr/io.h, the first line in the sketch) you will find that PORTB0 is defined as 0. In like manner, PORTB5 is defined as 5. You can see the pattern here. So, (1 << PORTB0) becomes (1 << 0). That means we take the number 1 and shift it left 0 times. That seems to make even less sense. It begins to make sense, however, if we look at 1 as 00000001. Nothing much happens to it if we shift it 0 times as in line 12 of the sketch. But, what about similar line 32. This means we shift 1 left by 5. Just move that 1 over 5 places to the left. This new value now becomes 00100000. Get it?
Now, we can talk about the OR operator. When we OR two binary digits, if either digit is a 1, the resulting value is a 1. A 0 result only corresponds to both digits being 0. So, if we started out with PORTB as 0b00000000 (all LEDs OFF) let's apply sketch line 12 and see what happens.
  00000000 PORTB
  00000001 OR with this binary number
  00000001 NEW PORTB value
This obviously turns the LED connected to PB0 ON, and that is the only one on. Now we wait one second and move on to sketch line 15, which is similar to line 12, except that the |= is replaced by &=, the AND compound operator. And, (1 << PORTB0) is now: !(1 << PORTB0). The exclamation point is the NOT symbol, for negation, another bitwise operator. We know that (1 << PORTB0) is 00000001. What then is !(00000001)? The answer is 11111110. Every bit is changed to its complement (1 becomes 0, 0 becomes 1).
The AND bitwise operator takes two bits and if either is a 0, or both are 0, the result will be a 0. The only way to get a 1 is if both bits are 1. So let's AND the contents of PORTB, 00000001, with 11111110:
  00000001 PORTB
  11111110 AND with this binary number
  00000000 NEW PORTB value
This turns the PB0 LED OFF. Obviously we could have written PORTB = 0; with the same effect, but what is the learning value in that? If you follow the logic you can see where sketch line 16, and beyond, turns the LED connected to PB1 one, for a second, before turning it off, and turning the next LED on, etc., etc.
Controlling those LEDs the way I did in that last sketch is rather silly. Lines 12 through 35 could have been written as:
PORTB = 0b00000001;
DELAY(1000);
PORTB = 0b00000010;
DELAY(1000);
      .
      .
      .
PORTB = 0b00100000;
DELAY(1000);
So why did I write all of that extra code? I wanted to illustrate the use of those bitwise functions because they are invaluable when writing to registers and memory. They are an elegant way of accessing individual bits in a field of other bits (our field is 8 bits because all ATmega registers are eight bits long). It's a way of altering some bits while leaving other bits alone. You could keep track of all the bits in a register at all times, but sometimes that is not possible. Other processes, either hardware or software, could change some bits in a register. You only want to access the bits you want to change and leave the others alone.
As you can see from what we have done before, if you wish to make a bit a 1, or assure it is a 1, OR it with a 1. OR the bits you don't want to change with a 0. Look at the example above.
If you wish to make a bit a 0, or assure it is a 0, AND it with a 0 and AND the others with a 1 to leave them alone. If you wish to toggle a bit, changing it from a 0 to a 1, or a 1 to a 0, EXCLUSIVE OR it with a 1, and EXCLUSIVE OR the others with a 0. If you study the examples above you can see how that works.

Sketch To Read From I/O Pins

I talked about writing to I/O pins in the previous sketches, so my last sketch shows an example of reading the logic level of an I/O pin:
This sketch sets pins PC0 to PC5 as inputs. Writing to PORTC will determine if an internal pull-up resistor will be connected to the pin. Writing a 1, connects the pull-ups. So writing 3F, in hexidecimal, writes a 1 to the lower 6 bits of the register.
Every second, the script sends the contents of PINC to the serial monitor running on the Pi. If PORTC is the register that outputs a logic level to the port C I/O pins, PINC is the register that records the logic level of external inputs of the port C I/O pins. If nothing is connected to an external pin, the internal pull-up resistor will set a logic 1 in the corresponding PINC register bit. If you connect that pin to ground, a logic 0 will be set in the register bit. Using the BIN built-in constant, will send the contents of the register in binary format.
If there is nothing connected to any of the port C pins, you will see:
  111111
  111111
  111111
etc.
However, if you connect PC0 to ground, for example, you will see:
  111110
  111110
etc. for as long as the ground is connected.

Wrapup

I hope this has been informative and if you are a beginner that you learned somethings useful.

Friday, July 19, 2013

The Gertboard - What Is It?

Gertboard Connected to Raspberry Pi
The Gertboard extends the usefulness of the Pi by allowing a variety of devices to be connected to the Pi, and, thus be controlled by the Pi. It is made up of individual circuits that have connector pins at their inputs and outputs. These circuits are connected to each other, to the Pi's GPIO pins, or to external devices. Jumpers are used to connect adjacent connector pins, and wires, with a socket on each end are used for other connections. Please note the colored wires in the photo above.
The Gertboard is available from SparkFun for $53 (USD). Newark Electronics has it for $50. Adafruit does not seem to carry it.
As is usual with most things you buy for the Pi (and the Pi, itself) the Gertboard does not come with any documentation. Yes, it ships with a CD, but that is simply a marketing tool to sell ARM development software. There is, however, a very comprehensive user's manual that explains every circuit. All circuits have at least one test routine. The manual shows how to connect the circuits for each test and explains the test software. The test software, in C++ and Python must be downloaded to the Pi. The manual details how to get, and install that software. Even though the user's manual references the schematic diagram for the board, these schematics are not included in the manual. However, these schematics are available as a separate file. The best way to get both the user's manual and the schematics is from the SparkFun page. So click here.
Gertboard - Illustration from "Gertboard User Manual". I added "Proto Area" to the illustration
So what are the features of the Gertboard?
  • The Gertboard plugs onto the GPIO connector of the Pi. Because the Gertboard's GPIO bottom facing connector socket connects directly to the top facing pins of the Pi's connector, it forms a single, physically stable, unit consisting of the two devices (see note below).
  • Twelve buffers for inputs to the Pi and twelve buffers to drive outputs from the Pi. Input buffers protect the Pi from inputs like sensors while output buffers reduce the loading of the Pi by output devices (like LEDs).
  • 12 LEDs
  • 3 Momentary push button switches
  • 6 High Voltage/High Current Outputs (open collector drivers). Each of these circuits can drive half an amp at 50 volts
  • A fused motor controller. Uses the pulse width modulation (PWM) capabilities of the Pi to control the speed and turning direction of the motor. This circuit can drive 2A at 18V.
  • Two 8 bit digital to analog (D to A) circuits.
  • Two 10 bit analog to digital (A to D) circuits.
  • And best of all an Atmel ATmega328 microcontroller IC. This is the same microcontroller as used by Arduino boards. Gordon Henderson, of Drogon Systems has developed all of the methods and procedures to interface the microcontroller to the Pi. The instructions to obtain all of the software, including the Arduino IDE (Integrated Development Environment) are provided by Gordon. To write programs (in C++) on the Pi for the Atmega328, and to get those programs loaded in the Atmega328, you use the Arduino IDE running on the Pi. The Gertboard User Manual provides the link to Gordon's web page. The Arduino IDE provides many sample programs and C++ help to get you started.
  • Prototyping area (outlined in blue in the figure above) to wire in your own circuitry. You will see where I use this area in my next blog post.
I have version 2 of the Gertboard. As I mentioned above, the Gertboard and the Pi connect directly together. This is not true for version 1. Version 1 requires a ribbon cable to connect to the Pi. I believe only Version 2 is available now. Version 1 came as a kit requiring the purchaser to assemble and solder parts to the board. Version 2 cones completely assembled. Version 1 used thru-hole parts with all IC's in sockets. Version 2 uses mostly surface mounted parts. In version 2, most IC's are thru-hole but only one IC, the ATmega microcontroller is in a socket. The other ICs are soldered to the PC board.