This is an old revision of the document!


Extrasensory perception for ESP-01 & RPi

RPi B+

ESP-01

This project adds three I2C devices to an ESP-01 or a Raspberry Pi.

The three devices are a Microchip MCP23016 digital I/O expander, NXP PCF8591 ADC/DAC and Microchip 24LC512 EEPROM.

These were chosen because they add useful capabilities to the ESP-01 or RPi and all three are available in DIP format from CPC in the United Kingdom.

Schematic

I2C bus

Address Device
0x20 MCP23016
0x48 PCF8591
0x50 24LC512

Probing the bus on the RPi with I2C Tools should reveal the following.

i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

MCP23016

Control Register Function
0 GP0 GPO input
1 GP1 GP1 input
2 OLAT0 GP0 output
3 OLAT1 GP1 output
6 IODIR0 GP0 direction
7 IODIR1 GP1 direction

To use the MCP23016 first set the GPIO direction register. Microchip use 1 for input and 0 for output. After that you can either read the input register or write to the output register.

I2C Tools on the RPi can demonstrate the MCP23016 GPIO.

Here we clear the output latch, set GP0.0 to an output, then set the pin high on the RPi.

i2cset -y 1 0x20 2 0
i2cset -y 1 0x20 6 0xFE
i2cset -y 1 0x20 2 1

The equivalent code for NodeMcu LUA on the ESP-01 is.

#!espy /dev/ttyUSB0

-- pin 3 = GPIO0
sda=3

-- pin 4 = GPIO2
scl=4

-- init I2C
i2c.setup(0,sda,scl,i2c.SLOW)

-- write MCP
function write_mcp(control,value)
        i2c.start(0)
        i2c.address(0,0x20,i2c.TRANSMITTER)
        i2c.write(0,control)
        i2c.write(0,value)
        i2c.stop(0)
end

-- init GP0.0
write_mcp(2,0)
write_mcp(6,0xFE)

-- blink LED on GP0.0 3 times
for i = 1, 3, 1 do
        write_mcp(2,1)
        print ("on")
        tmr.delay(1000000)
        write_mcp(2,0)
        print ("off")
        tmr.delay(1000000)
end

It is run via eSpy (to be documented).

./mcp.esp
> > > > > > > >> >> >> >> >> >> > > > > > >> >> >> >> >> >> >> on
off
on
off
on
off

Here on the RPi we set GP1.0 as an input then read it twice. The first read is with GP1.0 taken low and the second read with GP1.0 taken high.

i2cset -y 1 0x20 7 1
i2cget -y 1 0x20 1
0xde
i2cget -y 1 0x20 1
0xdf

Please refer to the data-sheet for full information for this part.

PCF8591

Control Register Function
0 channel 0 Read ADC 0
1 channel 1 Read ADC 1
2 channel 2 Read ADC 2
3 channel 3 Read ADC 3
+64 analog OE DAC output

To write to the DAC, we set the control to 64 and write a value between 0 and 255 which represents 0 to VREF volts on the output pin.

Using I2C Tools on the RPi we reset the output to 0V, then raise it to 1.6V and finally 3.3V.

i2cset -y 1 0x48 64 0
i2cset -y 1 0x48 64 128
i2cset -y 1 0x48 64 255

With NodeMcu LUA script, a simple ramp demo can be achieved like this.

#!espy /dev/ttyUSB0

-- pin 3 = GPIO0
sda=3

-- pin 4 = GPIO2
scl=4

-- init I2C
i2c.setup(0,sda,scl,i2c.SLOW)

-- write DAC
function write_dac(control,value)
        i2c.start(0)
        i2c.address(0,0x48,i2c.TRANSMITTER)
        i2c.write(0,control)
        i2c.write(0,value)
        i2c.stop(0)
end

-- DAC output
for i = 0, 255, 10 do
        write_dac(64,i)
        print (i)
        tmr.delay(100000)
end

When the script is run with eSPY we can see the DAC output ramp up and a running commentary.

> > > > > > > >> >> >> >> >> >> > > >> 
>> >> >> >> 0
10
20
30
...
230
240
250

To read from an ADC, we first send a control representing the channel, then we perform two reads. The first read starts the conversion process and the second read fetches the result (this also starts another conversion).

If we are using the DAC, then we must also set the analog OE bit else the DAC will be disabled.

With a potentiometer connected to AIN0 a reading was made on the RPi.

i2cset -y 1 0x48 64 ; i2cget -y 1 0x48 ; i2cget -y 1 0x48
0x1b
0x8d

The second value above is the new reading, the first is the previous reading.

This is simplified view of the operation of this device. Please read the data-sheet for the full details.

24LC512

I2C EEPROMs have varied addressing schemes. The simplest is a 8-bit address offset, another one where a block selection is made with an I2C address and a byte selection is made with an 8-bit address offset. Yet another, where the I2C address is fixed but it now has a 16-bit address offset and lastly one with both of the last methods combined.

Here we will demonstrate the 24LC512 which uses 16-bit addressing. The addressing byte order is high byte, low byte.

On the RPi we can reset the internal address pointer of the chip to 0 like this.

i2cset -y 1 0x50 0 0

To read, we first write an address to start at then begin reading, if we keep reading the address is auto-incremented.

i2cset -y 1 0x50 0 0
i2cget -y 1 0x50
0x55
i2cget -y 1 0x50
0xaa

If we want to write to a location we send the address followed by the byte of data.

i2cset -y 1 0x50 0 0 0xEE i
i2cset -y 1 0x50 0 0 
i2cget -y 1 0x50
0xee

On the ESP-01 we can use this NodeMcu LUA script to read the EEPROM.

#!espy /dev/ttyUSB0

-- pin 3 = GPIO0
sda=3

-- pin 4 = GPIO2
scl=4

-- init I2C
i2c.setup(0,sda,scl,i2c.SLOW)

-- read EEPROM
function read_eeprom(addrhigh,addrlow)
        i2c.start(0)
        i2c.address(0,0x50,i2c.TRANSMITTER)
        i2c.write(0,addrhigh)
        i2c.write(0,addrlow)
        i2c.stop(0)

        i2c.start(0)
        i2c.address(0,0x50,i2c.RECEIVER)
        c=i2c.read(0,1)
        i2c.stop(0)
        return c
end

-- read byte
reg = read_eeprom(0x00,0x00)

-- output byte
print(string.byte(reg))

Here the script is executed using eSPY (to be documented).

./eeprom.esp
> > > > > > > >> >> >> >> >> >> >> >> >> >> >> > > > > 238

eSPY is still being developed and as yet doesn't filter the LUA prompts from the output.

This overview gives enough information to use the device at a byte level, read the data-sheet for the page writing mode of operation.

Resources

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies