This is a strange one....
I am attempting to move a simple Python I2C LCD library for an HD44780 working on an RPi to an ESP8266 NodeMCU. The changes are limited to the supporting I2C library file and the changes only substitute the I2C initialization and write commands (see below). Here is the problem: Characters with the low order binary nibble of 1100 - 1111 appear on the LCD display as the corresponding characters with low order nibble 1000 - 1011 so ASCII 0x4C appears as the character ASCII 0x48, ASCII 0x4D appears as the character ASCII 0x49, ASCII 0x4E appears as the character ASCII 0x4A, and ASCII 0x4F appears as the character ASCII 0x4B. Therefore the string '@ABCDEFGHIJKLMNOP' appears on the display as '@ABCDEFGHIJKHIJKP' (no 'LMNO'), but any characters with low order nibble 0000 - 1011 appears properly. This phenomenon occurs/repeats for all characters for each high order nibble: (ASCII 0x2C, 0x2D, 0x2E, 0x2F appear as characters 0x28, 0x29, 0x2A, 0x2B, ASCII 0x3C, 0x3D, 0x3E, 0x3F appear as characters 0x38, 0x39, 0x3A, 0x3B, etc.). I added a print statement in the I2C library to show the low order nibble of the character being sent to the LCD via I2C bus and it is correct. This occurs regardless of where on the LCD display the characters appear. I have increased/decreased the delays, change the frequency in the initialization of the I2C bus to no avail. The display, I2C to LCD interface, and the (original) code operates properly on the RPi.
Thoughts? My code is far from perfect, but could the Micropython I2C library have a bug? What am I missing?
Thanks in advance!
Harold
I2C LCD Driver original source (for RPI): https://www.raspberrypi.org/forums/view ... 1&p=378524
Hardware: ESP8266 NodeMCU LoLin
Micropython version 1.8.6 (esp8266-20161110-v1.8.6.bin)
Original I2C_lib.py:
import smbus
from time import *
class I2C_device:
def __init__(self, addr, port=1):
self.addr = addr
self.bus = smbus.SMBus(port)
# Write a single command
def write_cmd(self, cmd):
self.bus.write_byte(self.addr, cmd)
sleep(0.0001)
. . .
Modified I2C_lib.py:
from machine import Pin, I2C
from time import *
class I2C_device:
def __init__(self, addr, port=1):
self.addr = addr
self.bus = I2C(scl=Pin(5), sda=Pin(4))
# Write a single command
def write_cmd(self, cmd):
self.bus.writeto(self.addr, chr(cmd))
sleep(0.0001)
print("CMD:",cmd >> 4) # Added for debugging - upper 4 bit is data sent to LCD !!!
(Deleted all the remaining excess/unused code in the library)
Weird I2C Problem?
Re: Weird I2C Problem?
Looks like bit 2 is stuck or set to 0 somewhere. It is hard to tell where, not seeing the full picture. Could be software or hardware.
Re: Weird I2C Problem?
I would avoid using the chr() function converting integers into text characters, and instead use ustruct to convert integer values into bytes. MicroPython uses UTF8 internally for representing text characters, and not all sequences of bytes are valid.
Re: Weird I2C Problem?
That did it!!!
Replaced 'self.bus.writeto(self.addr, chr(cmd))' with 'self.bus.writeto(self.addr, ustruct.pack("B",cmd))' and it works perfectly!
Thanks for the help!!!!!!!
Replaced 'self.bus.writeto(self.addr, chr(cmd))' with 'self.bus.writeto(self.addr, ustruct.pack("B",cmd))' and it works perfectly!
Thanks for the help!!!!!!!
Re: Weird I2C Problem?
Personally, I tend to use bytearrays. If you want to reduce memory allocations you can combine allocating a bytearray, and then create a memoryview onto it, and pass the memoryview to the write command.
Here's an example of using a bytearray (it will allocate a new one each time its called, like using ustruct.pack):
There was an example of using memoryview posted here: http://forum.micropython.org/viewtopic. ... 84&p=10115
Here's an example of using a bytearray (it will allocate a new one each time its called, like using ustruct.pack):
Code: Select all
packet = bytearray((0xff, 0xff, servo_id, 4, 3, 0x19, 1, 0))