I skimmed my old blog posts about MCP23s17 and made a summary.
I now remember that I started playing with MCP23S17 around 2013may12 and it took me about 1 week to build the MCP23S17/HC137 based SPI slave address decoder.
By that time I found my messy Python code was 4,000+ lines long. So I made up my mind to learn how to do Python modules, to break the long program into smaller, more manageable pieces.
Sunday, May 12, 2013 MCP23S17 board assembly notes
Now I am thinking of playing with SPI MCP23S17. Months ago I started with MCP23008 and MCP23017 I2C and find them interesting. But later I played with Guzunty Pi which uses SPI, and therefore a bit awkard to integrate with I2C MCP23017.
So I am now reading the datasheet again.
.END
Sunday, May 12, 2013 RPi I2C/SPI slave device address decoding design notes
I have been confused by the RPi's I2C and SPI device address decoding methods. So let me make a summary.
*** I2C
1. In Raspberry Pi, there are 2 I2C buses, I2C0 and I2C1. For now I have been using I2C1 at the P1 header. I2C0 is at the P5 header and I have not tried it.
2. For MCP230xx, each chip has 3 address pins A2, A1, A0 to select 8 devices. In other words, I2C0 can entertain 8 devices, I2C1 8 devices, altogether 16 devices.
*** SPI
1. In Raspberry Pi, there is only 1 SPI bus. This SPI bus have one chip has 2 select lines CE0, CE1, so can select 1 or 2 devices.
2. For MCP23Sxx, each chip also has 3 address pins A2, A1, A0 to select 8 devices. So SPI also altogether can select 1 of 16 devices.
*** Guzunty Pi
1. For Guzunty Pi, there is only one device select pin, by default wired to RPi's CS0. There are no address select pins. In other words, without additional hardware, SPI can select only 1 or 2 GPis.
*** Microchip ADC, Digital Potentiometer, and EEPROM
Microchip's ADC, Digital Pot, and EEPROM also only has CS pin but no extra address pins, therefore only 1 of 2 devices can be selected if no additional decoding hardware is used.
Now I am thinking of doing the following.
1. Use 1 MCP23S17 as the additional address decoder.
2. MCP230S17's 16 ports can all be assigned to be output. Therefore 16 devices can be selected. In other words, the total number selectable devices is multiplied by 16, or 256 devices. Actually only 255 devices because this first MCP23S17 is already used for decoding.
If using 1 of 8 address decoders such as 74HC138/137 3 line to 8 line 1 of 8 selectors, then the total number becomes roughly (16 - 1) * (16 / 3) * 8 == 680 devices, to many for human to handle!
Now I am going to make my first MCP23S17 address decoder board.
.END
Sunday, May 12, 2013 MCP23S17 test preparation notes
Before assembling and testing the new MCP23S17 board, I first tidied up the hardware. I have placed the following in an A4 sized tray.\
Haredware modules
1. Rpi Model A
2. GPi with 4 digit 7 segment LED
3. EEPROM 25LC256 x 2
Coupling details
1. RPi to GPi - SPI (CE1), PWM/CLK0, JTAG
2. RPi to EEPROM #2 - SPI (CE0)
Next step is to disconnect SPI (CE0) from EEPROM and to connect to the to be assembled MCP23S17.
In case anything goes wrong, white smoke coming up etc, the first thing after smoke settles down is to reconnect RPi to EEPROM and make sure all 3 modules RPi, GPi, and EEPROM are still working OK.
The program to do the above test is ft2080.py, as listed below.
TestGuzuntyPiLedDriver(chipEnableNumber = 1) # CE1
Test25Lc256() # CE0
The first function would check that GPi can still display time. The second function would check that the EEPROM could still write and read. If both goes well, then the basic RPi, GPi, EEPROM, and most importantly SPI CE0/CE1 hardware and software is more or less good.
.END
Sunday, May 12, 2013 MCP23S17 based SPI slave selector board
So I am soldering the MCP23S17 based SPI slave selector board. Last time when I played with I2C based MCP23017, I added 2N7000 based 3V3 to 5V0 level shifter, and followed by buffers using HC537. Or I used ULN2803 to do the level shift, and then inverter and buffer and so the hardware is messy and occupy too much space. But a buffer is necessary to drive stepping motors.
This time I am not going to drive stepper motors, so I don't use level shifting and buffering ICs. So I can use the proto board space generously.
.END
Monday, May 13, 2013 MCP23s17 finger burning hot!
I finished soldering the basic power and LED circuits and so started doing incrementdal testing. I first use crocodile clips to test by hand if all the LEDs can switch on and off. I was surprised to find that the LEDs are dimmer than usual. I thought perhaps this batch of cheap LEDs are poor quality. Anyway all LEDs work OK. Then I used my 20+ year old Sanwa multitester to check the IC power. I found the Vcc only 3.0V instead of 3V3, no wonder the LEDs are dim.
Then I by chance found the MCP23s17 surface is finger burning hot. I imediately switched off power and checked if I had the wrong numbering of pins. Then I realized that I made a very big careless mistake. I had the wrong polarity of power pins!
In my college and technician years. I almost always used the convention Vcc and Gnd. But this time I have Vss and Vdd. I thought SS is bigger than DD, so SS must be positive and DD negative or ground. But then I immediately understood that my casual guess is very wrong, and the convention has the oppostive polarity I guesses.
To make sure, I wikied "Vdd" and found that it is symbol used in military standard mil-std-498 dated 1994, no wonder I did not learn that in college ages ago.
I now also know that Vcc/Vee is for BJT, and Vdd/Vss is for FET.
One more lesson learnt is that the analog mutlimeter is not that precise in measuring voltages, though it is still very handy to check open/ short circuits.
To remind that the once burning hot IC might be damaged, I put a big white dot on its package surface.
IC power supply pin From Wikipedia, the free encyclopedia
Almost all integrated circuits (ICs) have at least two pins that connect to the power rails of the circuit in which they are installed. These are known as the IC's power supply pins. However, the labeling of the pins varies by IC family and manufacturer.
A generic labelled IC
Typical supply pin labeling
BJT FET
VCC VDD V+ VS+ Positive supply voltage
VEE VSS V− VS− Negative supply voltage
The simplest labels are V+ and V−, but internal design and historical traditions have led to a variety of other labels being used. V+ and V− may also refer to the inverting (−) and non-inverting (+) voltage inputs of ICs like op amps.
Sometimes one of the power supply pins will be referred to as ground (abbreviated "GND"). In digital logic, this is nearly always the negative pin; in analog integrated circuits, it is most likely to be a pin intermediate in voltage between the most positive and most negative pins.
While double subscript notation, where subscripted letters denote the difference between two points, uses similar looking placeholders with subscripts, the double letter supply voltage subscript notation is not directly linked (though it may have been an influencing factor).
.END
Monday, May 13, 2013 spidev_test compilation and execution problem
For I2C MCP23017, I used something called i2cdetect to make sure that linux finds the device. So I thought there should be a similar thing called spidetect.
Indeed I found the something called spidev_test.
I downloaded the program (This time I know the command to use is wget. Last time when I played with Guzunty, I did not know how to download in lunux, so I switched to Windows and did the Windows way of download and then the Windows way to detar, ..., taking me so much time!)
But when I complied the spidev.c there was a compilation error and I did not know how to fix it. So I download another spidev_test.c. This time I could compile it, but I could not run it. I used WinSCP to set the executive rights but still could not execute it. I used other tricks like sudo su to switch to root, and use path thing like "./xxx" but still no luck.
So I got into a stupid linux newbie trap and wasted 1 hour!
Lunch time!
Monday, May 13, 2013 spidev_test.c still not working
I read the expert's blog again and found that they don't run the compilation executive file spidev_test but sudo ./a.out. I vaguely remember a.out should be the c program's default output file. So the compilation actually runs the program.
Anyway, I complied and sudo ./a.out and got an all FF output. I guess this is a failure.
I remember I download the Python wrapper thing of spidev. So perhaps the spidev.c is for C only, not for python wrapper thing.
Anyway, I gave up and forget spidev_test.c for now, and move on to my own Python test functions.
pi@raspberrypi ~/python_programs/test_decoder $ gcc spidev_test.c
pi@raspberrypi ~/python_programs/test_decoder $ sudo ./a.out
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF
.END
Monday, May 13, 2013 SPI device detect program spidev_test.c problem solved!
I had the feeling that I might have missed something important in using the spidev_test.c. And I suddenly remember that for I2C there is no need to connect input signal to output, because input and output share the same line. But for SPI input and output have different wires, so might need to be connected. So I read the expert's blog again and found it indeed so.
So I connected MOSI to MISO and tested again. This time is OK. I found the output I hope to get.
I also remember that a.out is the default compilation output's name, not a data file. So I did the following to confirm my guesses.
1. Change the file name spidev_test.c to spidev_00_detect.c
2. gcc spidev_00_detect.c to a.out
3. Change filename a.out to spidev_00.detect.
4. $sudo ./spidev_oo_detect to get the expected output.
5. Connect MOSI to MISO.
I also read the program and found that the output 40 00 ... BA AD F0 0D etc appears to be some test input sample, nothing particular.
I also changed the device to /dev/spidev0.1. But it does not work. Perhaps spidev0.1 is not installed. It is not that important for now. So I will forget it for a while.
/*
SPI detect - tlfong01 2013may13
*** To detect SPI 0,0 ***
static const char *device = "/dev/spidev0.0";
*** To detect SPI 0,1 ***
static const char *device = "/dev/spidev0.1";
*** Test set up ***
1. Connect MOSI to MISO
*** Sample output ***
$ sudo ./a.out
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
FF FF FF FF FF FF
40 00 00 00 00 95
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
DE AD BE EF BA AD
F0 0D
...
.END
Monday, May 13, 2013 MCP23S17 detection testing notes
Now I have finished the point to point soldering of the SPI part of the MCP23s17 - power, SPi, address decoding. I have left the IO, interrupt, and reset connection after I have made sure that the RPi can detect this SPI device.
I will first take the SPI cable with MOSI and MISO loop back, to make sure everything is OK. Then I will connect the SPI cable to the real thing MCP2S17, to see if it can be detected.
.END
Monday, May 13, 2013 MCP23S17 detection failure!
So I ran the spi_00_detect, first with the SPI cable looping back MOSI to MISO, then with the cable connected to the MCP23S17.
The looping back detection is OK. But no luck for the MCP23S17. It was all zeros!.
I remember I forgot to set the Reset pin to no reset. So there is still hope!
pi@raspberrypi ~/python_programs/test_decoder $ sudo ./spi_00_detect
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
FF FF FF FF FF FF
40 00 00 00 00 95
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
DE AD BE EF BA AD
F0 0D
pi@raspberrypi ~/python_programs/test_decoder $ sudo ./spi_00_detect
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00
pi@raspberrypi ~/python_programs/test_decoder $ date
Mon May 13 08:56:55 UTC 2013
pi@raspberrypi ~/python_programs/test_decoder $
.END
Monday, May 13, 2013 spidev_test.c - testing spi looping back, or detecting a SPI device?
So I soldered a 10K to pull up MCP23S17's reset pin, and tried again. But spidev_test.c still returns all 0's, and loop back test is OK, not all zeros.
I thought the MCP23S17 might be dead because earlier I might have burnt it with a wrong polarity power, making it crazily hot. So I swapped with a new MCP23S17, but still no luck.
Then I suspected spidev_test is only for checking if SPI is more or less working, at least loop back output to input.
So I used ft2080.py to test the EEPROM at spi CE0 and Guzunty Pi LED driver at CE1, and found both OK. Then without disconnecting any hardware, I tested spidev_test and found still all 0's, and then looping back still looks OK (not all 0's, and second line begins with 0x40 etc.)
Then I retested EEPROM and MCP23S17 a couple of times, with either power on and off. I found spidev_test always returns all 00's, and rarely all FF's.
I came to the conclusion that spidev_test, unlike i2cdetect, can tested SPI more or less OK, but CANNOT BE USED TO DETECT A SPI DEVICE.
So I guess I should forget spidev_test and move on to using Python to test MCP23S17.
.END
Monday, May 13, 2013 MCP23s17 detector design notes
Now I am reading the MCP23X17 datasheet and try to see how to change the I2C functions into SPI functions. I see that the only difference is in the I2C/SPI interface part. So I look closely at their control byte and address format.
1.3.3.1 SPI Write Operation
The SPI write operation is started by lowering CS. The Write command (slave address with R/W bit cleared) is then clocked into the device. The opcode is followed by an address and at least one data byte.
1.4.2 ADDRESSING SPI DEVICES (MCP23S17)
The MCP23S17 is a slave SPI device. The slave address contains four fixed bits and three user-defined hardware address bits (if enabled via IOCON.HAEN) (pins A2, A1 and A0) with the read/write bit filling out the control byte. Figure 1-3 shows the control byte format. The address pins should be externally biased even if disabled (IOCON.HAEN = 0).
1.0 DEVICE OVERVIEW
The MCP23017/MCP23S17 (MCP23X17) device family provides 16-bit, general purpose parallel I/O expansion for I2C bus or SPI applications. The two devices differ only in the serial interface.
• MCP23017 – I2C interface
• MCP23S17 – SPI interface
The MCP23X17 consists of multiple 8-bit configuration registers for input, output and polarity selection. The system master can enable the I/Os as either inputs or outputs by writing the I/O configuration bits (IODIRA/B).
The data for each input or output is kept in the corresponding input or output register. The polarity of the Input Port register can be inverted with the Polarity Inversion register. All registers can be read by the system master.
The 16-bit I/O port functionally consists of two 8-bit ports (PORTA and PORTB). The MCP23X17 can be configured to operate in the 8-bit or 16-bit modes via IOCON.BANK.
There are two interrupt pins, INTA and INTB, that can be associated with their respective ports, or can be logically OR’ed together so that both pins will activate if either port causes an interrupt.
The interrupt output can be configured to activate under two conditions (mutually exclusive):
1. When any input state differs from its corresponding Input Port register state. This is used to indicate to the system master that an input state has changed.
2. When an input state differs from a preconfigured register value (DEFVAL register).
The Interrupt Capture register captures port values at the time of the interrupt, thereby saving the condition that caused the interrupt.
The Power-on Reset (POR) sets the registers to their default values and initializes the device state machine.
The hardware address pins are used to determine the device address.
1.3 Serial Interface
This block handles the functionality of the I2C (MCP23017) or SPI (MCP23S17) interface protocol.
The MCP23X17 contains 22 individual registers (11 register pairs) that can be addressed through the Serial Interface block, as shown in Table 1-2.
1.3.3 SPI INTERFACE
1.3.3.1 SPI Write Operation
The SPI write operation is started by lowering CS. The Write command (slave address with R/W bit cleared) is then clocked into the device. The opcode is followed by an address and at least one data byte.
1.3.3.2 SPI Read Operation
The SPI read operation is started by lowering CS. The SPI read command (slave address with R/W bit set) is then clocked into the device. The opcode is followed by an address, with at least one data byte being clocked out of the device.
1.3.3.3 SPI Sequential Write/Read
For sequential operations, instead of deselecting the device by raising CS, the master clocks the next byte pointed to by the Address Pointer. (see Section 1.3.1 “Byte Mode and Sequential Mode” for details regarding sequential operation control).
The sequence ends by the raising of CS.
The MCP23S17 Address Pointer will roll over to address zero after reaching the last register address.
1.4 Hardware Address Decoder
The hardware address pins are used to determine the device address. To address a device, the corresponding address bits in the control byte must match the pin state. The pins must be biased externally.
1.4.2 ADDRESSING SPI DEVICES (MCP23S17)
The MCP23S17 is a slave SPI device. The slave address contains four fixed bits and three user-defined hardware address bits (if enabled via IOCON.HAEN) (pins A2, A1 and A0) with the read/write bit filling out the control byte. Figure 1-3 shows the control byte format. The address pins should be externally biased even if disabled (IOCON.HAEN = 0).
1.5 GPIO Port
The GPIO module is a general purpose, 16-bit wide, bidirectional port that is functionally split into two 8-bit wide ports.
The GPIO module contains the data ports (GPIOn), internal pull-up resistors and the output latches (OLATn).
Reading the GPIOn register reads the value on the port. Reading the OLATn register only reads the latches, not the actual value on the port.
Writing to the GPIOn register actually causes a write to the latches (OLATn). Writing to the OLATn register forces the associated output drivers to drive to the level in OLATn. Pins configured as inputs turn off the associated output driver and put it in high-impedance.
1.6 Configuration and Control Registers
There are 21 registers associated with the MCP23X17, as shown in Table 1-5 and Table 1-6. The two tables show the register mapping with the two BANK bit values.
Ten registers are associated with PortA and ten are associated with PortB. One register (IOCON) is shared between the two ports. The PortA registers are identical to the PortB registers, therefore, they will be referred to without differentiating between the port designation (i.e., they will not have the “A” or “B” designator assigned) in the register tables.
.END
Monday, May 13, 2013 MCP23S17 Python Programming - Passing SPI function as a parameter to another function
As I am trying to port the MCP23017 functions to MCP23S17, I found 2 big problems.
First, I found that I misunderstood the register architecture of the MCP23X17. So my functions are using misleading parameter names, thus making the program very difficult to understand.
Second, I found SPI a bit messy to handle than I2C, because I2C functions such as smBus1.write_byte_data( ) are global functions, meaning that smBus need not be passed as parameter and can be used freely. For SPI however, spi channel (spidev.SpiDev()) is an object created each time used. So it need to be passed as a parameter to a function.
But I am not sure if a SPI function can be passed as a parameter.
For example, I am not sure if I can I do the following.
def SpiWrite(spiChannelWriteFunction, writeList):
spiChannelWriteFunction(writeList)
def Test25Lc256():
...
spiEeprom = spidev.SpiDev()
spiEeprom.open(0, 0)
...
SpiWrite(spiEeprom.xfer2, [EePromCommandWriteLatchEnable])
I tried it and to my surprise, passing the spiChannel's function as a parameter to another function is acceptable to Python.
So I am going to use this function of a function thing to do my MCP23S17 programming.
def SpiWrite(spiChannelWriteFunction, writeList):
spiChannelWriteFunction(writeList)
def Test25Lc256():
EepromCommandWriteLatchDisable = 0x04
...
spiEeprom = spidev.SpiDev()
spiEeprom.open(0, 0)
...
SpiWrite(spiEeprom.xfer2, [EePromCommandWriteLatchEnable])
...
.END
Tuesday, May 14, 2013 CP23S17 programming - passing spi channel object by reference to a function
On second thought, it is more neat and tidy to pass the spi channel object to the spi write function, instead of the spi channel's function.
So the spi write function is newly defined like this:
def SpiWrite(spiChannel, spiWriteList):
spiChannel.xfer2(spiWriteList)
and called like this:
SpiWrite(spiEeprom, [EePromCommandWriteLatchEnable])
# *** SPI write/read functions ***
def SpiWrite(spiChannel, spiWriteList):
spiChannel.xfer2(spiWriteList)
def Test25Lc256():
...
spiEeprom = spidev.SpiDev()
spiEeprom.open(0, 0)
...
EepromCommandWriteLatchDisable = 0x04
...
SpiWrite(spiEeprom, [EePromCommandWriteLatchEnable])
...
.END
Tuesday, May 14, 2013 MCP23S17 detection program writing notes
Now I have started writing the MCP23s17 detection program. This program does the following 2 things.
Part 1. Setup both ports's 8 pins of MCP23S17 at SPI0, CE0 as output.
Part 2. Write 0x55 to Port A, 0xaa to Port B.
So far I have written Part 1. Next step is testing it.
...
.END
Tuesday, May 14, 2013 MCP23S17 detection program debugging notes
I also wrote some print statement to help debugging.
TestMcp23s1701(spiChannelNumber = 0, spiChipEnableNumber1bit = 1, spiChipSubAddress3bit = 3)
# *** Sample output ***
# mcp23s17WriteCommand = 01000110
# mcp23s17RegisterAddress = 00000000
# mcp23s17WriteDataByte = 00000000
# mcp23s17WriteCommand = 01000110
# mcp23s17RegisterAddress = 00000001
# mcp23s17WriteDataByte = 11111111
# *** Mcp23x17 Functions v1.0 tlfong01 2013may14 ***
# *** Constants and variables ***
# * Port type *
PortA = 0
PortB = 1
# * Register address array index *
InputOutputDirectionIndex = 0
InputPolarityIndex = 1
InterruptEnableIndex = 2
DefaultValueIndex = 3
CompareModeIndex = 4
BankInterruptPinModeIndex = 5
PullUpIndex = 6
InterruptFlagIndex = 7
InterruptCaptureIndex = 8
PortStatusIndex = 9
OutputLatchIndex = 10
# * Data constant bytes *
All8pinOutput = 0x00
All8pinInput = 0xff
All8bitOne = 0xff
All8bitZero = 0x00
All8bitPullUp = 0xff
# * Direction setting bytes *
Upper8bitOneLower8bitZero = 0xff00
Upper8bitZeroLower8bitOne = 0x00ff
Upper4bitOneLower4bitZero = 0xf0
Upper4bitZeroLower4bitOne = 0x0f
Upper8pinInputLower8pinOutput = 0xff00
Upper8pinOutputLower8pinInput = 0x00ff
Upper4pinInputLower4pinOutput = 0xf0
Upper4pinOutputLower4pinInput = 0x0f
RegisterAddressArrayMcp23s17 = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x1d, 0x0f, 0x11, 0x13, 0x15]
Mcp23s17WriteCommand = 0b01000000
Mcp23s17ChipSubAddress0 = 0b000
# *** SPI write/read functions ***
def SpiWrite(spiChannel, spiWriteList):
spiChannel.xfer2(spiWriteList)
def SpiRead(spiChannelWriteFunction, writeList):
readList = spiChannelWriteFunction(writeList)
# *** Mcp23s17 Functions ******************************************************
def GetRegisterAddress(registerAddressArray, registerIndex, portType):
if (portType == PortA):
registerAddress = registerAddressArray[registerIndex]
if (portType == PortB):
registerAddress = registerAddressArray[registerIndex + 11]
return registerAddress
def WriteDataByteMcp23s17(spiChannel, spiChipSubAddress3bit, registerAddressArray, registerIndex, portType, dataByte):
mcp23s17WriteCommand = Mcp23s17WriteCommand | (spiChipSubAddress3bit << 1)
mcp23s17RegisterAddress = GetRegisterAddress(registerAddressArray, registerIndex, portType)
mcp23s17WriteDataByte = dataByte
PrintEightBitPattern("mcp23s17WriteCommand = ", mcp23s17WriteCommand)
PrintEightBitPattern("mcp23s17RegisterAddress = ", mcp23s17RegisterAddress)
PrintEightBitPattern("mcp23s17WriteDataByte = ", mcp23s17WriteDataByte)
spiWriteList = [mcp23s17WriteCommand, mcp23s17RegisterAddress, mcp23s17WriteDataByte]
SpiWrite(spiChannel, spiWriteList)
def SetupMcp23s17Ports(spiChannel, spiChipSubAddress3bit, portAsetupByte, portBsetupByte):
WriteDataByteMcp23s17(spiChannel, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, InputOutputDirectionIndex, PortA, portAsetupByte)
WriteDataByteMcp23s17(spiChannel, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, InputOutputDirectionIndex, PortB, portBsetupByte)
def TestMcp23s1701(spiChannelNumber, spiChipEnableNumber1bit, spiChipSubAddress3bit):
# *** Set up SPI channel ***
spiChannelMcp23s17 = spidev.SpiDev()
spiChannelMcp23s17.open(spiChannelNumber, spiChipEnableNumber1bit)
# *** Set up MCP23s17 ports ***
SetupMcp23s17Ports(spiChannelMcp23s17, spiChipSubAddress3bit, All8pinOutput, All8pinInput)
# *** Write 0x55 to Port A and 0xaa to Port B ***
# To be written, ...
# *** Description ***
# Open SPI channel for MCP23S17 at sub address 0b000
# Assign MCP23s17 Port A and Port B all 8 pins as output
# Write 0x55 to Port A and 0xaa to Port B
# *** Sample call to test MCP23S17 with SPI channel 0, CE0, chip address 0
# TestMcp23s17(spiChannelNumber = 0, spiChipEnableNumber1bit = 0, spiChipSubAddress3bit = 0)
Tuesday, May 14, 2013 MCP23S17 detection program tested OK
I soldered only A0 (pin 21) and B0 (pin1) and ran the program to set up Ports A and B all output. I used a DVM to check the output and found them zeros.
I then wrote 2 statements to output 0x55 to both Port A and Port B.
# *** Write 0x55 to Port A and 0xaa to Port B ***
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, DataByte0x55)
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortB, DataByte0x55)
I then ran the test again. This time everything works OK. The LEDs connected to A0 and B0 turns on.
So this MCP23S17 detection program is tested OK.
.END
TestMcp23s1701(spiChannelNumber = 0, spiChipEnableNumber1bit = 0, spiChipSubAddress3bit = 0)
def TestMcp23s1701(spiChannelNumber, spiChipEnableNumber1bit, spiChipSubAddress3bit):
# *** Set up SPI channel ***
spiChannelMcp23s17 = spidev.SpiDev()
spiChannelMcp23s17.open(spiChannelNumber, spiChipEnableNumber1bit)
# *** Set up MCP23s17 ports ***
SetupMcp23s17Ports(spiChannelMcp23s17, spiChipSubAddress3bit, All8pinOutput, All8pinOutput)
# *** Write 0x55 to Port A and 0xaa to Port B ***
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, DataByte0x55)
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortB, DataByte0x55)
# *** Mcp23x17 Functions v1.0 tlfong01 2013may14 ***
# *** Constants and variables ***
# * Port type *
PortA = 0
PortB = 1
# * Register address array index *
InputOutputDirectionIndex = 0
InputPolarityIndex = 1
InterruptEnableIndex = 2
DefaultValueIndex = 3 CompareModeIndex = 4
BankInterruptPinModeIndex = 5PullUpIndex = 6
InterruptFlagIndex = 7
InterruptCaptureIndex = 8
PortStatusIndex = 9
OutputLatchIndex = 10
# * Data constant bytes *
All8pinOutput = 0x00
All8pinInput = 0xff
All8bitOne = 0xff
All8bitZero = 0x00
All8bitPullUp = 0xff
# * Direction setting bytes *
Upper8bitOneLower8bitZero = 0xff00
Upper8bitZeroLower8bitOne = 0x00ff
Upper4bitOneLower4bitZero = 0xf0
Upper4bitZeroLower4bitOne = 0x0f
Upper8pinInputLower8pinOutput = 0xff00
Upper8pinOutputLower8pinInput = 0x00ff
Upper4pinInputLower4pinOutput = 0xf0
Upper4pinOutputLower4pinInput = 0x0f
# * Data bytes
DataByte0x55 = 0x55
RegisterAddressArrayMcp23s17 = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x1d, 0x0f, 0x11, 0x13, 0x15]
Mcp23s17WriteCommand = 0b01000000
Mcp23s17ChipSubAddress0 = 0b000
# *** SPI write/read functions ***
def SpiWrite(spiChannel, spiWriteList):
spiChannel.xfer2(spiWriteList)
def SpiRead(spiChannelWriteFunction, writeList):
readList = spiChannelWriteFunction(writeList)
# *** Mcp23s17 Functions ******************************************************
def GetRegisterAddress(registerAddressArray, registerIndex, portType):
if (portType == PortA):
registerAddress = registerAddressArray[registerIndex]
if (portType == PortB):
registerAddress = registerAddressArray[registerIndex + 11]
return registerAddress
def WriteDataByteMcp23s17(spiChannel, spiChipSubAddress3bit, registerAddressArray, registerIndex, portType, dataByte):
mcp23s17WriteCommand = Mcp23s17WriteCommand | (spiChipSubAddress3bit << 1)
mcp23s17RegisterAddress = GetRegisterAddress(registerAddressArray, registerIndex, portType)
mcp23s17WriteDataByte = dataByte
PrintEightBitPattern("mcp23s17WriteCommand = ", mcp23s17WriteCommand)
PrintEightBitPattern("mcp23s17RegisterAddress = ", mcp23s17RegisterAddress)
PrintEightBitPattern("mcp23s17WriteDataByte = ", mcp23s17WriteDataByte)
spiWriteList = [mcp23s17WriteCommand, mcp23s17RegisterAddress, mcp23s17WriteDataByte]
SpiWrite(spiChannel, spiWriteList)
def SetupMcp23s17Ports(spiChannel, spiChipSubAddress3bit, portAsetupByte, portBsetupByte):
WriteDataByteMcp23s17(spiChannel, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, InputOutputDirectionIndex, PortA, portAsetupByte)
WriteDataByteMcp23s17(spiChannel, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, InputOutputDirectionIndex, PortB, portBsetupByte)
# *****************************************************************************
# Function - TestMcp23s1701
# Description -
# Open SPI channel for MCP23S17 at sub address 0b000
# Assign MCP23s17 Port A and Port B all 8 pins as output
# Write 0x55 to Port A and 0xaa to Port B
# *****************************************************************************
# *** Sample call to test MCP23S17 with SPI channel 0, CE0, chip address 0
# TestMcp23s17(spiChannelNumber = 0, spiChipEnableNumber1bit = 0, spiChipSubAddress3bit = 0)
def TestMcp23s1701(spiChannelNumber, spiChipEnableNumber1bit, spiChipSubAddress3bit):
# *** Set up SPI channel ***
spiChannelMcp23s17 = spidev.SpiDev()
spiChannelMcp23s17.open(spiChannelNumber, spiChipEnableNumber1bit)
# *** Set up MCP23s17 ports ***
SetupMcp23s17Ports(spiChannelMcp23s17, spiChipSubAddress3bit, All8pinOutput, All8pinOutput)
# *** Write 0x55 to Port A and 0xaa to Port B ***
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, DataByte0x55)
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortB, DataByte0x55)
...
.END
Wednesday, May 15, 2013 MCP23S17 software interrupt ideas
Now that RPi recognizes the MCP23S17 and also drives GA0, GB0's LEDs, I have confidence to move on. I have now completed the point ot point soldering of the remaining GAx, GBx pins, and also Reset, IntA and IntB.
At first I thought that this IOx is all O and no I, so there is no use for interrupt pin. On second thought, I might make use of the IOx chip's interrupt on change thing to trigger interrupt when 1 of the 16 pins changed value by software. But I am not sure if this makes any sense.
.END
Wednesday, May 15, 2013 MCP23S17 using 74HC137 3-to-8 decoder
Now I am thinking of using four 74HC137 3-to-8 decoders to decode SPI devices.
Four pins can be used to select 1 of 8, so MCP23S17's 16 pins, if all assigned as output, can be grouped to four groups of 4 each. to select 4 SPI devices, 1 from each 8 device group.
.END
Wednesday, May 15, 2013 MCP23S17 using HC137 to select 1 of 8 devices (not necessarily SPI devices)
Now I am using MCP23S17's GA0~GA2 for HC137's A0~A2, and GA3 for HC137's ~LE. I have written another demo function for MCP23S17 to select HC137 channel 3. The LED #3 turns on as expected. So far so good. Time I went to bed.
# *** MCP23S17 Demultiplexing ***
def TestMcp23s17Demux(spiChannelNumber, spiChipEnableNumber1bit, spiChipSubAddress3bit):
# *** Set up SPI channel ***
spiChannelMcp23s17 = spidev.SpiDev()
spiChannelMcp23s17.open(spiChannelNumber, spiChipEnableNumber1bit)
# *** Set up MCP23s17 ports ***
SetupMcp23s17Ports(spiChannelMcp23s17, spiChipSubAddress3bit, All8pinOutput, All8pinOutput)
# *** For SPI 0, CE1, MCP23S17 (000) select 1 of 8 device (using GA0~2 for A2~A0, GA3 for ~LE)
# Hc137AddressLatchDisable = 0x00
# Hc137AddressLatchEnable = 0x08
Hc137AddressLatchDisable = 0x03
Hc137AddressLatchEnable = 0x0b
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchDisable)
WriteDataByteMcp23s17(spiChannelMcp23s17, spiChipSubAddress3bit, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchEnable)
# *** Hold ***
while True:
pass
# *** Close SPI channel ***
spiEeprom.close()
...
.END
Thursday, May 16, 2013 MCP23S17 address decoder and 3V3 to 5V0 logic level up shifter and display driver
Now I am mixing and matching some old 5V0 logic circuit boards I used with Arduino and Netduino.
1. The 4 of 8 bits input ULN2803 x2 based 3V3 to 5V0 logic level up shifter is now connected to MCP23S17 GA0~3. So the 3V3 3 bit address is displayed by the 5V0 MC14495.
2. The MC14495 has hexidecimal 4 bit input. However MCP23S17 GA0~3 is address data, GA3 is ~LE, so I need get rid of this GA3 bit, in order not to mislead.
.END
Friday, May 17, 2013 MCP23S17 SPI demultiplexing testing notes
Now I am doing SPI demultiplexing test. The setup is summarized below.
1. RPi JTAG, PWM/CLK, SPI (with CE0, CE1) go to bread board at middle front.
2. SPI with CE0 go to MCP23S17 which is set to 16 pins output GA0~7, GB0~7.
3. MCP23S17 GA0~3 go to input of HC137 (3V0), HC137 output go to bread board (D)
4. MCP23S17 GB0~3 go to input of HC137 (5V0), HC137 output go to bread bread (E)
5. GPi wth 4 digit LED SPI Gnd, SCLK, MOSI, MISO go to C, CE goes to HC137 (3v3) output Y0.
6. EEPROM #1 SPI Gnd, SCLK, MOSI, MISO go to C, CE goes to HC137 (3v3) output Y1.
7. EEPROM #2 SPI Gnd, SCLK, MOSI, MISO go to C, CE goes to HC137 (3v3) output Y2.
Next step is test 3 SPI devices GPi, EEPROM #1, and EEPROM #2 in time sequence, using MCP23S17 to do the demultiplexing.
.END
Friday, May 17, 2013 SPI Demux bad design notes
So now the SPI slaves GPi, EEPROM etc will not have their ~CS lines connected to RPi SPI CE1. Instead they connect to HC137 Yn, and RPi will select Yn to select which SPI to operate.
But then I found a problem. Now RPI SPI CE1 is not connected to anything, and HC137 Yn takes its place. I need to select/disselect Yn for each EEPROM read/write operation. Very soon I found this awkard to handle, and I am not sure if the EEPROM timing using HC137 Yn is still acceptable.
After some thought, I found it a bad design. A cleaner design would be to use a two input OR gate to handle each SPI device. Now the original slave's ~CS goes to one input of the OR gate, and HC137 Yn goes to the other input.
Now let me think aloud. If Yn is not selected, the Yn = High would make the OR gate output always high, so nothing happens. If Yn is selected, therefore Low, then RPi CE1 would go through the OR gate like transparent.
This way I don't need to modify the EEPROM or GPi's software. In other words, the solution is using hardware to save software adaption.
.END
Friday, May 17, 2013 SPI Demux circuit using 74HC32
Now I am using HC32 Quad 2 Input OR gate to test my design. I first connect 1 of the 2 OR gate input to gnd (to simulate the HC137 Yn selection), RPi CE1 to the other input of the OR gate, and output of the OR gate to EEPROM ~CS.
I found everything OK. Then I connected the OR gate input which originally connected to ground to HC137 Y3, use software to select Y3 and check EEPROM write then read. Everything looks OK.
So next step is to shift the HC137 from bread board to proto board.
.END
TestMcp23S17Eeprom()
def TestMcp23S17Eeprom():
# *** Set up SPI channel ***
spiChannel = spidev.SpiDev()
spiChannel.open(0, 0)
# *** Set up MCP23s17 ports ***
SetupMcp23s17Ports(spiChannel, 0, All8pinOutput, All8pinOutput)
# *** Select HC137 Output 0 (GPi 3 digit LED) ***
Hc137AddressLatchDisable0 = 0x00
Hc137AddressLatchEnable0 = 0x08
Hc137AddressLatchDisable1 = 0x01
Hc137AddressLatchEnable1 = 0x09
Hc137AddressLatchDisable7 = 0x07
Hc137AddressLatchEnable7 = 0x0f
# *** Write Eeprom ***
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchDisable1)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchEnable1)
Write25Lc256(spiChannel, channelNumber = 0, chipEnableNumber = 1, dataByte = 0xaa)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchDisable7)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchEnable7)
# *** Read Eeprom ***
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchDisable1)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchEnable1)
Read25Lc256(spiChannel, channelNumber = 0, chipEnableNumber = 1, dataByte = 0x5a)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchDisable7)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, Hc137AddressLatchEnable7)
# *** Close SPI channel ***
spiChannel.close()
...
.END
Saturday, May 18, 2013 EEPROM functions refactoring notes
Now I am tidying up FongToy 2088 functions. Below is the EEPROM read byte function refactored.
def Read25Lc256DataByte(spiChannel, channelNumber, chipEnableNumber, eepromStartAddress):
spiChannel.open(channelNumber, chipEnableNumber)
PrintDoubleSpaceLine("*** Start reading 25LC256 ***")
# *** 25LC256 instructions ***
EePromCommandRead = 0x03
eepromStartAddressUpper = eepromStartAddress >> 8
eepromStartAddressLower = eepromStartAddress & 0x00ff
# *** SPI variables and constants ***
readSpiDataList = [0x00, 0x00, 0x00, 0x00, 0x00]
DummyDataByte = 0x00
# *** Read back data at address 0x0000 ***
readSpiDataList = spiChannel.xfer2([EePromCommandRead, eepromStartAddressUpper, eepromStartAddressLower, DummyDataByte])
PrintDoubleSpaceLine("*** Read back data byte written ***")
PrintEightBitPattern("Read back byte 0 = ", readSpiDataList[0])
PrintEightBitPattern("Read back byte 1 = ", readSpiDataList[1])
PrintEightBitPattern("Read back byte 2 = ", readSpiDataList[2])
PrintEightBitPattern("Read back byte 3 = ", readSpiDataList[3])
dataByte = readSpiDataList[3]
return dataByte
.END
Saturday, May 18, 2013 SPI decoding hardware test setup notes
I am also refactoring the SPI decoder hardware test setup.
.END
Sunday, May 19, 2013 SPI 1 of 8 slave decoder / selector assembly and testing notes
Now I have soldered part of the 1 of 8 SPI slave decoder/selector. I tested it with Guzunty Pi LED driver with manual input and found everything OK. So I will go completing all the boring soldering.
.END
Sunday, May 19, 2013 SPI slave selector function development notes
Now I writing a function to test the SPI selector thing.
def TestMcp23S17SpiSlaveSelector():
# *** Set up SPI channel ***
spiChannel = spidev.SpiDev()
spiChannel.open(0, 0)
spiCe1 = 1
# *** Set up MCP23s17 ports ***
SetupMcp23s17Ports(spiChannel, spiCe1, All8pinOutput, All8pinOutput)
# *** Select HC137 Output 0 (GPi 3 digit LED) ***
Hc137AddressLatchDisable0 = 0x00
Hc137AddressLatchEnable0 = 0x08
Hc137AddressLatchDisable1 = 0x01
Hc137AddressLatchEnable1 = 0x09
Hc137AddressLatchDisable7 = 0x07
Hc137AddressLatchEnable7 = 0x0f
Hc137AddressLatchDisable2 = 0x02
Hc137AddressLatchEnable2 = 0x0a
spiDeviceNumber = 3
spiDecoderAddressWriteByte = spiDeviceNumber
spiDecoderAddressLatchByte = spiDecoderAddressWriteByte | 0x80
# *** Write Eeprom ***
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, spiDecoderAddressWriteByte)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, spiDecoderAddressLatchByte)
Write25Lc256(spiChannel, channelNumber = 0, chipEnableNumber = 1, dataByte = 0xaa)
# *** Read Eeprom ***
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, spiDecoderAddressWriteByte)
WriteDataByteMcp23s17(spiChannel, 0, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, spiDecoderAddressLatchByte)
readBackDataByte = Read25Lc256DataByte(spiChannel, channelNumber = 0, chipEnableNumber = 1, eepromStartAddress = 0x0300)
PrintEightBitPattern("Read back data byte = ", readBackDataByte)
# *** Close SPI channel ***
spiChannel.close()
...
.END
Monday, May 20, 2013 SPI slave selector board testing notes
This morning I will carry on testing the SPI 1/8 slave selector board, using EEPROM 25LC256 to check out things.
.END
Monday, May 20, 2013 fongtoy 2096 refactoring notes
Now I am refactoring ft2090 to 2096, getting stuck in spi read/write function because I always forgot the strange thing of SPI write and read happen at the same time, and to read, you must first write.
# *****************************************************************************
# TestMCP23S17SpiSlaveSelector() v1.0 tlfong01 2013may20hkt1101
# Description
# Setup 2 SPI channels, one for MCP23S17 (sub address 0), one for 25LC256
# Setup MCP23S17 Port A and Port B all 8 pins output
# Select EEPROM 25LC256
# Write 1 byte to EEPROM
# Read 1 byte from EEPROM
# *****************************************************************************
def SpiWrite(spiChannel, spiWriteList):
spiReadList = spiChannel.xfer2(spiWriteList)
return spiReadList
def SelectSpiSlave(spiChannel, mcp23s17SubAddress, spiSlaveSubAddress):
loadDecoderDataControlByte = spiSlaveSubAddress | 0b00000000 # bit 4 = 0 loads HC137 decoder
latchDecoderDataControlByte = spiSlaveSubAddress | 0b00001000 # bit 4 = 1 latches HC137 decoder
WriteDataByteMcp23s17(spiChannel, mcp23s17SubAddress, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, loadDecoderDataControlByte)
WriteDataByteMcp23s17(spiChannel, mcp23s17SubAddress, RegisterAddressArrayMcp23s17, OutputLatchIndex, PortA, latchDecoderDataControlByte)
def WriteEepromDataByte(spiChannel, startAddress, dataByte):
# *** Constants and variables ***
EePromCommandWriteLatchEnable = 0x06
EepromCommandWrite = 0x02
FiveMilliSeconds = 0.005
startAddressUpper = startAddress >> 8
startAddressLower = startAddress & 0x00ff
# *** Write data byte ***
SpiWrite(spiChannel, [EePromCommandWriteLatchEnable])
time.sleep(FiveMilliSeconds)
SpiWrite(spiChannel, [EepromCommandWrite, startAddressUpper, startAddressLower, dataByte])
time.sleep(FiveMilliSeconds)
def ReadEepromDataByte(spiChannel, startAddress):
# *** Constants and variables ***
EepromCommandRead = 0x03
FiveMilliSeconds = 0.005
DummyDataByte = 0x00
readSpiDataList = [0x00, 0x00, 0x00, 0x00, 0x00]
startAddressUpper = startAddress >> 8
startAddressLower = startAddress & 0x00ff
# *** Read data byte ***
readSpiDataList = SpiWrite(spiChannel, [EepromCommandRead, startAddressUpper, startAddressLower, DummyDataByte])
dataByte = readSpiDataList[3]
return dataByte
def TestMcp23S17SpiSlaveSelector01(mcp23S17Address, eepromSubAddress, testStartAddress, testDataByte):
# *** Set up SPI channel 00 for MCP23S17, channel 01 for EEPROM 25LC256 ***
SpiChannel0 = 0
SpiChipEnable0 = 0
SpiChipEnable1 = 1
Mcp23s17SubAddress0 = 0
spiChannel00 = spidev.SpiDev()
spiChannel00.open(SpiChannel0, SpiChipEnable0)
spiChannel01 = spidev.SpiDev()
spiChannel01.open(SpiChannel0, SpiChipEnable1)
# *** Set up MCP23s17 Port A all out to drive HC137 #1, Port B to drive 2 74HC137 #2 ***
All8pinOutput = 0x00
SetupMcp23s17Ports(spiChannel00, Mcp23s17SubAddress0, All8pinOutput, All8pinOutput)
# *** Select EEPROM 25LC256 ***
SelectSpiSlave(spiChannel00, Mcp23s17SubAddress0, eepromSubAddress)
# *** Write Eeprom ***
WriteEepromDataByte(spiChannel01, startAddress = testStartAddress, dataByte = testDataByte)
print "Write data byte = ", hex(testDataByte)
# *** Read Eeprom ***
readBackDataByte = ReadEepromDataByte(spiChannel01, startAddress = testStartAddress)
print "Read data byte = ", hex(readBackDataByte)
# *** Close SPI channel ***
spiChannel00.close()
spiChannel01.close()
...
.END
Monday, May 20, 2013 MCP23S17 selecting 2 EEPROMs
Now I have written a function to select 2 SPI EEPROMs. Everything go smoothly.
Next step is to add the Guzunty Pi 4 digit LED module.
...
# *** Select EEPROM 25LC256 #1 at HC137 Y0 ***
SelectSpiSlave(spiChannel00, mcp23s17SubAddress, eepromSubAddress1)
# *** Write Eeprom ***
testDataByte = 0x51
testStartAddress = 0x0411
WriteEepromDataByte(spiChannel01, startAddress = testStartAddress, dataByte = testDataByte)
print "Write data byte = ", hex(testDataByte)
# *** Read Eeprom ***
readBackDataByte = ReadEepromDataByte(spiChannel01, startAddress = testStartAddress)
print "Read data byte = ", hex(readBackDataByte)
# *** Test EEPROM #2 ***
# *** Select EEPROM 25LC256 #[2] at HC137 Y1 ***
SelectSpiSlave(spiChannel00, mcp23s17SubAddress, eepromSubAddress1)
# *** Write Eeprom ***
testDataByte = 0x34
testStartAddress = 0x0411
WriteEepromDataByte(spiChannel01, startAddress = testStartAddress, dataByte = testDataByte)
print "Write data byte = ", hex(testDataByte)
# *** Read Eeprom ***
readBackDataByte = ReadEepromDataByte(spiChannel01, startAddress = testStartAddress)
print "Read data byte = ", hex(readBackDataByte)
...
.END
Monday, May 20, 2013 Python module learning notes
This afternoon when I tried to add Guzunty Pi to the HC137 decoder circuit, I found the decoder seems overloaded and could not output a low bit. I removed the Guzunty Pi, and the whole things works again. But then even 2 EEPROMs seem to overload the circuit. I tied only 1 EEPROM and everything works fine. But there seemed an intermittant short circuit somewhere and loaded down the 3V3 to about 2V0. I tidied up the messy wiring and the short circuit disappeared. But then even with no EEPROM the decoder still could not decode.
I gave up after trying my luck for an hour, doing various tests. But still found things behaving strangely. So I gave up and went for supper. On my way to eat, I suddenly reminded myself that there should be an oscillation, because the problem happened when I tried to add the Guzunty Pi LED module which uses a high frequency clock, perhaps from 5MHz down to 2K. One other thing is that I am using long wring of about 1m for the SPI connection. So it was rather sure that there was an oscillation.
One thing I must do now is forget Guzunty Pi, for the time being. I also remember that some weeks earlier I found GPi could not start or get hanged, perhaps it was also related to oscillation.
The other problem is that when I tried to find functions to do troubleshooting, I found it more and more difficult to find the functions I want, because my program is getting to a laughably 4,000 lines long! It is like a big wot of chop suet and fried noddle. It is hard to find which function is buried somewhere.
I started learning Python last October, so it is about 7 months now. I have been too lazy to learn new things like module and objects. But I think it is time to take a break from hardware and try to organize my messy code into modules. Then hopefully my troubleshooting life would be easier.
I googled the following Python Module tutorial.
...
.END
No comments:
Post a Comment