Page 1 of 1

I2C workaround

Posted: Wed Jan 21, 2015 12:05 pm
by speedracer
I recently attached an Adafruit 1.2" LED backpack to an EZsbc1. This backpack uses the I2C bus for setup and data transfer. Initialization of the driver chip on this card (Holtek HT16K33) requires sending it three command bytes, each preceded by the board address. Intially, I used the command

c$=chr$(0x21)
i2cwr(0xe0,0,c$,1)

hoping this would send the hex value 21 to the board at address 0xe0. After considerable frustration, I finally put a scope on the clock and data lines of the I2C bus and discovered that I was sending THREE bytes instead of two. After some thought, I tried this command

i2cwr(0xe0,0x21,c$,0)

and it worked. So anyone trying to send simple byte commands to an I2C slave might want to keep this workaround in mind.

For what it's worth, this is the test code I used to verify the operation of the LED backpack card. I only intend to display three digits in my application -- a gps speedometer for my racecar -- so I included leading zero blanking. Please keep in mind, I haven't programmed in BASIC in maybe 20 years.

' LEDtest2
'
' Controls the adafruit 1.2" LED backpack card


' constants and codes for numbers 0-9
dim num(10) = 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f
ht15k33 = 0xe0 ' address of adafruit backpack card - really!
osc_on = 0x21 ' code to turn oscillator on
disp_on = 0x81 ' code to turn display on
disp_off = 0x80 ' code to turn display off
bright = 0xef ' code for max brightness
z$ = chr$(00) ' code for a blank digit/colon

' initialize the I2C bus on the EXsbc1 card
i2cinit(100000) ' initialize the I2C bus
i2ctime(10)

' initialize the backpack card
c$=""
i2cwr(0xe0,0x21,c$,0) ' trick to send <adr> <cmd> only
delay(100)
i2cwr(0xe0,0xef,c$,0)
delay(100)
i2cwr(0xe0,0x81,c$,0)
delay(100)

print "Input a 1-4 digit number: ";
INPUT number
repeat
gosub display4dig:
print "Input a 1-4 digit number (<0 to quit): ";
INPUT number
until number<0
print ""
print "Count-up display, max count = ";
input maxcnt
maxcnt=max(maxcnt,1)
for k=0 to maxcnt
number=k
gosub display4dig:
delay(250)
next k
end

' subroutine to display up to 4 digits with leading zero blanking
' call with an integer in the variable 'number'
display4dig:
d1=int(number/1000)
if d1>0 then
d1$=chr$(num(d1+1))
else
d1$=chr$(0x00)
endif

d2=int((number-d1*1000)/100)
if d2>0 or number>99 then
d2$=chr$(num(d2+1))
else
d2$=chr$(0x00)
endif

d3=int((number-d1*1000-d2*100)/10)
if d3>-1 and number>9 then
d3$=chr$(num(d3+1))
else
d3$=chr$(0x00)
endif

d4=int((number-d1*1000-d2*100-d3*10))
d4$=chr$(num(d4+1)) ' always display 0 or more

i2cwr(0xe0,0x00,d1$,1)
i2cwr(0xe0,0x02,d2$,1)
i2cwr(0xe0,0x04,z$,1) ' clear dp's
i2cwr(0xe0,0x06,d3$,1)
I2CWR(0Xe0,0x08,d4$,1)
return

Re: I2C workaround

Posted: Thu Jan 29, 2015 11:16 pm
by Andries Pretorius
Thanks for sharing!

Andries Pretorius