Refactoring Electronics (Hardware V00K)

Side Project:

I still haven’t gotten the OLED display working.  I am beginning to question Pinouts and even if the driver IC listed by the seller(s) is correct.  At this point I can’t even tell if the device is seeing my commands. I checked the board for shorts/solder bridges and even replaced the OLED display. I still can’t get anything to show up on the display.

I think a reasonable test would be to measure current to the display and send it a power on command.  If I am sending commands correctly, I should see a change in current draw.  After that, I will try working through the commands available in the datasheet for a SSD1332 chip looking for a change in the display or the current draw.

Refactoring:

Just like refactoring the code, It’s time to refactor the electronics design.  I checked on my feature request on the Espressif forum. Nothing new has happened.  So I am considering adding an external ADC to measure voltages.

Planning and Research:

Continue reading

Refactoring

Update:

No new information on the ADC feature request on Espressif”s forums.

Side Project:

I have started layout of the SSD1332 Breakout PCB.  I finished the layout and ordered PCBs from OSHPark.  Based on the datasheet for the SSD1332, I can get significantly better performance by using it in one of the 8 bit bus modes.  Someone suggested that I look at STM32 processors to drive the display with.  I will be considering that option this week.

Better Firmware:

Continue reading

Design Decision

Side Project:

I am moving forward with the Compass toy prototyping.  I am designing a simple breakout PCB for testing the display. I may put the display breakout for sale on Tindie.

Project Intent:

The primary goal of this project/blog is to show electronics design start to finish.

The design goal is an inexpensive in circuit chip programmer that will work for most devices available.

Options:

The Raspberry Pi Zero was released November of 2015 at a price of $5 US each.  I even got one with a copy of MagPi.  To Make it run any code at all, it needs a power supply and microSD card.

Of course I could continue with the current design.

Common components:

Both the Raspberry Pi and the current design need the following components.

Printed Circuit Board
Battery for power supply and charging circuit
Vpp Supply
Level Shifter Circuit
External ADC(Still undecided for current design)
USB to serial Bridge (not sure it’s necessary for R Pi)

Additional components for Raspberry Pi:

Continue reading

Layout check … continued

With the new check plots I made last week, I checked the layout net by net like I did back in Sept 5, 2015. I am still uncertain about the pinout of the ESP-12F modules. To test it, I removed the ESP-12E installed on the board I am currently using, and replaced it with a new ESP-12F.  I had to be careful that the jumper wires all got back to where they were before removing the module.

The new module programmed first try but didn’t boot correctly.  I had forgot to upload default values, the flash comes programmed for a different memory layout.  Once I installed the default settings, it booted up correctly.  I had removed the test for HSPI/SPI RAM, so I went back into the code and re-enabled the Hello World ram test.

I went into serialInit() and changed the line DISPLAY_MENU(); to DISPLAY_MENU_W_SPI(); Re-compiled and tested.  Unfortunately the result was not “Hello World”. When I cleaned up the code, I made the write to SPI RAM easier, but I need to initialize the hspi.  I started connecting my mixed signal oscope to analyze what was happening on the SPI bus.  And… I found a loose jumper wire.  The one that connects the chip select between the ESP-12F and the SPI RAM. Once this was connected, the extra stuff I had put into the software became unnecessary.  I deleted the extra code and it works just fine.  The firmware is back to where it was before I started testing. There are no changes to upload.

This means that the circuit is tested and the current layout is ready to send to fabrication.  I zipped up the gerber files. Then checked pricing with PCBway, DFRobot, and Seeed Studio.  With shipping PCBway came in a little less at US $19.  With PCBway, I have to wait for a design review before they will give me a final price and allow me to pay for it. Usually this is pretty quick but depends on the day it is submitted.

Have you bought boards from Chinese manufacturers? How quickly did you get them?

Hardware Iteration (hardware V00H)

The last time I worked on the electronics was when I got the switching boost circuit working.  The crashes I saw with it is why I did so much code work since then.  This week, I wanted to get back into electronics.  Since it has been a while I started by reviewing the schematic.  First thing I reviewed was the Lithium cell charger circuit.  It matches the reference design in the AAT3672 datasheet and it matches the PCB.  I should test it before I spin another set of boards.  I put a note on the schematic to remind myself to do that.

I then looked at the switched boost circuit. It turns out I don’t need L2, the real problem was in software. I removed L2 from the schematic. The resistor R5 was changed to 47 Ohms. I updated that on the schematic.  Next I looked at the USB to Serial Bridge, I have two cuts with Jumpers on the board, I checked them against the schematic. The schematic matches the patch I had made.

Next I compared the patches I made to the SPI RAM against a pinout of the ESP-12F I found online.  ESP-12F pins 9 – 14 on the schematic matches the PCB with the modifications I have made.  Pin 16 is no longer connected and Pin 18(GPIO0) is connected.  I had made this change back when I was testing the SPI RAM. With this change, D4, Q6, R26, and R27 are unnecessary. I removed them from the schematic and tied GPIO0 to U2 Pin1 and disconnected it from U10 Pin 6. I then tied GPIO15 to U10 Pin6 with a net label called A_SEL.  I have yet to test IO2 and IO3, Which will require running the RAM in QIO mode. In QIO mode, IO2/IO3 shouldn’t matter because when I read them back out of the RAM will come back out on the same pins they went in.

I have yet to test the level shift chip(U3).  I don’t like how hard U3 is to solder so I researched a different part to do the same thing. The new part I found is a TI TXB0108PWR which works very nearly the same as what I already had designed in but comes in a 20 pin TSSOP which is easier to solder.  The Pin order is different. The part is only US $1.88 in singles at Digikey.  I proceeded to change U3 to the new part on the schematic.  The datasheet recommends that OE be held low until both Vcca and Vccb are on.  I put a PNP transistor in to pull OE low anytime Vt is not driven.  As I dug into the datasheet, I found that this chip would not work for I2C.

So I did a little more research and I found another chip from TI.  The TXS0108EPWR works with SPI and I2C.  It has the same pinout as the TI TXB0108PWR so adding it to the schematic was really easy, I changed the name in the schematic.  This part is US $2.00 on Digikey.

txs0108esch

I uploaded the updated hardware design to Github. Click on the hardware link in the right column to go get it.

Have you used level shifters before? Have you decided on a chip only to find out that it was missing one crucial component? How did you fix it?

Sigma Delta Testing V00I

Last Week I wrote to  and read from the SPI RAM but only verified it with a logic analyzer.  I read from the registers and sent them out on the serial line. Like before, I did a hello world test and actually expected to see hello world after the menu. It didn’t work, I forgot to take care of several things in the software. I adjusted the software a little at a time testing with each change until it started working.

Once I saw “Hello World” in my serial console, I decided to start testing the Sigma_Delta output.  I want to know if it causes system crashes without the voltage boost circuit having any connection to power. Without R5 or L2 installed, the boost circuit really can’t have much affect on the system. Q5 also isn’t installed so the Sigma Delta output on GPIO4 is driving to high impedance.

I changed the firmware so that GPIO4 is the Sigma Delta output.  Then I un-commented out the line in user_init() that configures and enables the Sigma Delta output.  Before, I had a very limited range of prescaler I could use for the Sigma Delta signal. I can set the sigma delta prescaler from 0 to 100.  I was expecting to get full range which would be 0 to 255.  So I went back into the software and looked to see if I made a math error.  The math is simple and it looks right so I decided to look at the Sigma Delta register definition.  The register definition matches the way the code is written.  I checked Kolban’s ESP8266 book, it didn’t have anything useful about the Sigma Delta.  I looked for it in Espressif’s  SDK programming guide and found nothing. Next I searched using Google. This turned up the page I had originally found on Espressif’s bbs.  It describes the prescaler being a value of 0 to 255. So I still don’t know why going bigger than 99 causes the system to crash.  It is not clear what is causing this rebooting.

I will look at the Sigma Delta software more next week. I have uploaded the current status of the code to GitHub.

I would love to hear from you readers.  The only comments I get are spam!

Switching to SPI from HSPI Firmware V00I

I decided to try to use the SPI module instead of overlap mode this week.  I went into the code that writes and reads from the SPI and changed the working registers to SPI in place of HSPI. I had to store and restore 6 variables in the writeRam() and readRam() functions.  It worked but sent more data than expected. I noticed that I left the overlap init code in place, I removed it and tried again. I still got more data than I expected. I searched for HSPI and found one place that I had forgot to change it to SPI. I fixed that and now it is working. The code is also working without crashing.

SPI Write Hello World

Next I added the read function back into the main code to see what would happen. I saw only 4 bytes on the SPI bus. I had missed a value change I needed to make the SPI read 12 bytes.    It seems that either the DMA or an Interrupt routine is taking control of the SPI Hardware before i can finish a read. I disabled interrupts and it’s still only sending the command (3) and the address (0) plus 6 more clock cycles.

Incomplete SPI Read

Since SPI is used for loading code into internal RAM as well as running it directly from flash, it might be difficult to figure out when I can use it for the SPI  RAM.  I had the HSPI appearing to work in overlap mode.  Since I can switch between overlap and normal mode on the fly, maybe the HSPI in overlap mode is the best choice. In the writeRam() and readRam() functions, I changed the all references to SPI Registers to HSPI Registers and I commented out the code to save and restore the SPI Registers.  I used find and replace to simplify the changes.  I searched on (SPI) and filled in the replace with (HSPI) and then I selectively hit REPLACE/FIND for each instance.

Then I built and tested the code, hopefully back to where I was last week.  I got all zeros but I hadn’t done a write since I started working on it this time. So I put the writeRam() just before the readRam() in user_init() and tried again. On the logic analyzer, the write looks exactly like I would expect. The read is still not getting anything but zeros for the data section.  Next step is to look at the HOLD and WP lines on the SPI RAM. I had to look at the datasheet to see what state they needed to be in to work correctly.  Looking at the datasheet, there is no WP line, but there is a HOLD line.  If HOLD is low, the serial interface of the chip doesn’t work.  I clipped one more logic analyzer line on to Pin 7 of the SPI RAM.  The signal looks identical to MOSI.  I should have cut the trace when I was re-wiring this board but I missed it. I proceeded to cut it and add a jumper from the HOLD line to the ESP12E Pin 11. this is my best guess for the pins to use SQI. With Re-testing I got a successful read from the chip.

SPI Successful read

Next week, I need to verify the SPI working registers have the expected values from the ram.  I put the current version of the code up on GitHub.

How do you handle cutting in circuit changes?  Do you have any stories about a design change only to find it best to go back to the original plan?

Understanding HSPI Firmware V00H

What I wasn’t understanding last week is the definition of HSPI_CS.  It is the same as CS0 in the HSPI module.  So when I turn on overlap mode, of course, it maps to SPI_CS0.  That leaves me with setting the HSPI to use CS1(GPIO1/U0TXD) or CS2(GPIO0).  Since I use U0TXD for reprogramming the module, CS1 is unavailable.

I cut the trace going to U2 CS0 and added a jumper wire to GPIO0.  I then changed the code to use CS2 to enable the RAM.  This included setting the HSPI to use CS2 and setting GPIO0 MUX to be SPICS2.  And I got what looks like a successful write to the SPI RAM.

Successful SPI Write

The byte command (2) followed by 24bit address (0) followed by the data.  The first four bytes of data are “lleH”.  This is backwards to what I was planning, I can change it by setting a bit or changing the bytes I put into the registers. As long as I read them back the same way, it really doesn’t matter as long as I read and write aligned to 4 byte words.  The data is one byte short, I had a typo sending only 11 bytes of data.

Note: When data is aligned to 4 bytes, it means you need to read or write only on increments of 4 bytes.  So you would only Write or Read to/from addresses that in hexadecimal end in 0, 4, 8, or C. Since this chip is a 32 bit processor, this is required often.

I then decided to implement the hard coded read command.  I copied the write code, changed the command from 2 to to 3, set the HSPI to read back  and zeroed out the working registers so that I can see if they have been filled with the data I stored in the RAM. Then I commented out the writeRam() call in user_init and added readRam() in it’s place. Doing this without powering down, I should get the data back without having to write it again. I forgot to switch the length to the receive length register; I fixed this then I got back all zeros for the data.

Unsuccessful SPI read

I see the command (3) followed by the address (0) followed by 12 Bytes of data(0). So I have more debugging to do.  My first guess is the WP or HOLD lines of the chip are not doing what I need them to do.

I have gotten a better understanding of the SPI hardware on the ESP8266.  It looks to me that I can get the same control by just using the main SPI channel to control my RAM chip.  This needs testing.  I will need to save any registers I change and restore them when I am done accessing the RAM.  This will also have to be done from code that runs from internal RAM.

I have put the current state of the code on GitHub.  Use the link under the search box on the right side of this page.

Have you used chips with similar SPI configuration?  I like that I can have any bit length of data on the SPI bus, this will be useful for JTAG data. Have you worked directly with JTAG data?

HSPI Frustrations

I cut the traces going to the SPI RAM that I figured out were wrong last week. On the PCB at U3 Pin3, and Pin5 I cut one trace each and on Pin6 I cut two traces.  Most of these cuts are under the chip so I made them before re-soldering the chip to the board.  Of course then I added wire jumpers to route the signals to match the schematic. I then added pins to connect the logic analyzer to.

Cut traces Chip Installed Rewired SPI

 

 

 

 

Last week I was looking at the the SPI driver code by MetalPhreak on Github as well as his blog to figure out how to send commands and data out and receive back over SPI.  The register SPI_USER is used to configure the SPI, SPI_USER1 sets up data length, SPI_USER2 sets up the command length and Command data.  Additionally, there is an SPI_Address Register that I can use to select an address in the RAM. Finally SPI_W0 to SPI_W15 are the data packet working registers — This is where I will put my “Hello World”.  I can write or read up to sixteen 4 byte words.  My RAM is organized in bytes so I will be putting bytes of data into the working registers.

So for initial setup I think the following should work for writing data.

SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_MOSI);

CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE|SPI_USR_MISO);

 

The following should work for reading data:

SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_MISO);

CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE|SPI_USR_MOSI);

The CS_SETUP and CS_HOLD parameters affect chip select timing. Setup is before clocking out data, hold is after.  Some chips need extra set up or hold time.  It will not affect performance significantly so I just turned each on by default so I don’t have to wonder if this RAM chip needs them. USR_COMMAND tells it to send the data in the command register. Likewise USR tells it to send the data in the Address Register.  USR_MOSI tells the hardware that there is data in the Working registers to be sent out. USR_MISO tells the hardware that I want to receive data into the working registers.

For the SPI RAM I want to send a command(Write), An Address(0), and 12 Bytes of data(“Hello World”).  This totals 16 bytes of data to be sent on the SPI bus:

1 byte for the command: 0x02
3 bytes for the address: 0x000000 and
12 bytes of data: “Hello World” including 1 trailing NULL.

For my first attempt to write to RAM I chose to hard code the instructions.
In my SPIRam.c File I had already created a function called writeRam.  I deleted it’s contents, and added the stuff to make this work.
void writeRam(char data[], int length){

SET_PERI_REG_MASK(SPI_USER(HSPI),
SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE|SPI_USR_MISO);

WRITE_PERI_REG(SPI_USER1(HSPI), (((12*8-1)&SPI_USR_MOSI_BITLEN)<<SPI_USR_MOSI_BITLEN_S)| //12 Bytes of data out
((7&SPI_USR_MISO_BITLEN)<<SPI_USR_MISO_BITLEN_S)| //Ignored for write
((23&SPI_USR_ADDR_BITLEN)<<SPI_USR_ADDR_BITLEN_S)); //address is 24 bits A0-A8

WRITE_PERI_REG(SPI_ADDR(HSPI),(uint32) 0x000000<<(32-24)); //write 24-bit address

WRITE_PERI_REG(SPI_USER2(HSPI),
(((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S) | 0x02)); // Write Command

WRITE_PERI_REG(SPI_W0(HSPI),0x48656C6C); //"Hell"
WRITE_PERI_REG(SPI_W1(HSPI),0x6F20576F); //"o Wo"
WRITE_PERI_REG(SPI_W2(HSPI),0x6C6400); //"rld",NULL,NULL

SET_PERI_REG_MASK(SPI_CMD(HSPI), SPI_USR);// Tell hardware to do it.

}
After fixing my typos, I compiled and loaded the code.  The system booted without hanging. then I hooked up the logic analyzer to look for the data being transferred and it didn’t work. The Chip select line(U3 Pin1 ) doesn’t go low for a frame of data.  This means the chip never gets selected to write to.

With several hours of tinkering, I finally have it close, but it is still not working correctly.  The CS0 pin is being activated when the HSPI CS pin is being activated.  So I am getting the correct sequence of bytes when HSPI CS is low, but CS0 is low at the same time.

HSPI almost working

I have not posted a new copy of the software, I don’t believe it is useful to anyone yet.  It isn’t even useful to learn from.

Have you had similar frustrations? Have you gotten the HSPI to work in overlap mode?

Please leave a comment below.

 

ESP-12E pinout differences

A while ago, I found an e-book about the 8266.  It’s called “Kolban’s book on ESP8266” by Neil Kolban.  He compiled a lot of information on the ESP8266.  I decided to look at this book to see if it has any useful information concerning the HSPI.  It has very little to say about HSPI.  The book lists the API calls without any detail.  What is important is it lists a GitHub repository that has very easy to read example code.  The author of the example code also has a blog with a very good description of how to use the SPI registers.

Since I have the HSPI working with one byte, I decided to try to get the Overlap mode working before trying to add functionality.  I retested with the code from last week and got the same results. Let’s hear it for consistency!  Then I put the call to hspi_overlap_init() in my code just before the sending of data.  Without changing which pins the logic analyzer is attached to, I expect to see chip select to go low and but not see any clock or data, they should move to the other pins.  The data didn’t change pins.  I connected to the SPI bus to see if the data is being sent on both buses.  I checked what should be the clk line and got what looks like data. Next I checked what should be the MOSI line and it looks like the CLK line should look. I created the table below while doing the testing.  I did find that data was on both sets of pins.

Pin#(expected) — Most likely signal
PIN10(MISO) — ?
PIN11(IO2) — ?
PIN12(CLK) — ?
PIN13(IO3) — MOSI
PIN14(MOSI) — CLK

I grabbed the first build of the board to see if it acted the same. I soldered component leads to each of the SPI signals I was interested in and then attached the logic analyzer to those pins as I needed.  With the old board it looks like MOSI is on Pin13 and CLK is on Pin12.  There are definitely different pinouts of the ESP12E from (I assume) different manufacturers.  This could be a problem if I go to any kind of mass production.  There is a newer version of the chip ESP-12F that seems to match the pinout of the chip I currently have.  I don’t see any evidence on the web of different pinouts of the 12F yet.  This needs more research.

I will have to change the layout again but I can test the HSPI with RAM by cutting the traces and putting jumpers in to correctly wire the chip.  I went back and modified the schematics to reflect these changes.  Since the pinout for the 12F matches the lines I am pretty sure of, I used it to update the schematic.  I changed the labels on the Pins of the chip then changed the connections to the SPI RAM.

SPI Pinout FixESP-12F

Have you had to work with manufactures changing specs on you? Or obsoleting a chip? How did you deal with it?