Cheap I2C OLED display with 08M2

tecnition_ted

New Member
Hi Hippy,
tried the above and now have four 0000 on the OEL. am I right in thinking the program above only refreshes the OEL once? (I may be completely wrong) How would I get it to loop to change the character's as there updated by the readi2c ?
 

tecnition_ted

New Member
I have also tried BINTOASCII and get the same result. four 0's on the OEL. I don't understand as when you look up some of the values generated by both sets of commands they should represent ASCII 2 and 3 so don't know why these wouldn't be shown on the OEL.
"I am concentrating mainly on Volt for now as SOC has reached 0"

Code:
;code replaced line 70 to 82
poke 28," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "
poke 44," "," ","V","o","l","t"," "
bintoascii w4,b12,b13,b14,b15,b16
Poke 51, b12
Poke 52, b13
Poke 53, b14
Poke 54, b15
poke 60," "," ","S","o","c"," "," "
bTmp = SOC / 1000 // 10 + "0" : Poke 67, bTmp
bTmp = SOC / 100 // 10 + "0" : Poke 68, bTmp
bTmp = SOC / 10 // 10 + "0" : Poke 69, bTmp
bTmp = SOC // 10 + "0" : Poke 70, bTmp
poke 76," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "
 

Attachments

tecnition_ted

New Member
Ok I have confirmed the display is not updating by adding to 63 to 70 this code. b18 increments but the screen does not show it. This would mean that the information is not updating on the screen and as b18 does increment then this part of the program is cycling. I am guessing there needs to be a clear command sent to the OEL and a reload of the information into the OEL memory.

Any help appreciated

code:
let b18=47
main:
; Insert your programme code here and then poke 28-91 with message to be displayed
;data to send to display (4 * 16)

b18 = b18+1 ;add 1 to an ascii value
poke 28," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "
poke 44," "," ","V","o","l","t"," ",b18 ; see if b18 is incremented and what is displayed on screen
 

tecnition_ted

New Member
Ok narrowed it down to the commands sent by i2c to the BQ chip are stopping the information going to the OEL. separated read program into Start1: and the OEL program into Start2: b18 does increment to show the program is cycling but the OEL does not change this would indicate an issue with the i2c
 

hippy

Technical Support
Staff member
separated read program into Start1: and the OEL program into Start2:
That's not a great idea as using 'start1' and 'start2' will unintentionally cause the 08M2 to operate in multi-tasking mode which will likely cause quite a few problems.

I would suggest reverting back to what you had.

the commands sent by i2c to the BQ chip are stopping the information going to the OEL.
If both are I2C devices then you will need to issue a HI2CSETUP command before accessing each.
 

tecnition_ted

New Member
Noted it didn't work.
This did work! the display is now showing updated Volt and SOC but the symbols on the display are moving left. along the same lines, I have tried adjusting the amount of characters without success and they appear correct.

Why did setting up the master again work to change which slave it was looking at???? I was hoping you could just change the slave address then read it but if you try this then it does nothing on the OEL.

any ideas

Code:
symbol counter = w0
symbol subcounter = b2
symbol fontlookup = b3
symbol pixels = b4
symbol displaybank = b5
symbol Volt = w4
symbol SOC = w5
symbol bTmp = w6



; save Font codes in EEPROM

eeprom 0,(124,130,130,130,124) ; 0 (ASCII 48)
eeprom 5,(136,132,254,128,128) ; 1
eeprom 10,(196,162,162,146,140) ; 2
eeprom 15,(68,130,146,146,108) ; 3
eeprom 20,(48,40,36,254,32) ; 4
eeprom 25,(110,138,138,138,114) ; 5
eeprom 30,(124,146,146,146,100) ; 6
eeprom 35,(2,2,2,2,254) ; 7
eeprom 40,(108,146,146,146,108) ; 8
eeprom 45,(30,18,18,18,254) ; 9 (ASCII 57)
eeprom 50,(254,18,18,18,254) ; A (ASCII 65)
eeprom 55,(254,146,146,146,108) ; B
eeprom 60,(254,130,130,130,130) ; C
eeprom 65,(254,130,130,68,56) ; D
eeprom 70,(254,146,146,146,130) ; E
eeprom 75,(254,18,18,18,2) ; F
eeprom 80,(254,130,130,146,242) ; G
eeprom 85,(254,16,16,16,254) ; H
eeprom 90,(130,130,254,130,130) ; I
eeprom 95,(226,130,254,2,2) ; J
eeprom 100,(254,16,40,68,130) ; K
eeprom 105,(254,128,128,128,128) ; L
eeprom 110,(254,2,254,2,254) ; M
eeprom 115,(254,4,56,64,254) ; N
eeprom 120,(254,130,130,130,254) ; O
eeprom 125,(254,18,18,18,12) ; P
eeprom 130,(124,130,162,66,188) ; Q
eeprom 135,(254,18,50,82,140) ; R
eeprom 140,(222,146,146,146,246) ; S
eeprom 145,(2,2,254,2,2) ; T
eeprom 150,(126,128,128,128,126) ; U
eeprom 155,(30,96,128,96,30) ; V
eeprom 160,(254,128,254,128,254) ; W
eeprom 165,(198,40,16,40,198) ; X
eeprom 170,(6,8,240,8,6) ; Y
eeprom 175,(194,162,146,138,134) ; Z (ASCII 90)





initialise:
; initialise i2c for display (ID 0x78) and then send power up instructions

hi2csetup i2cmaster,$78,i2cfast,i2cbyte
hi2cout 0x80,(0xAE,0x00,0x00,0xB0,0x20,0x00,0xD5,0x80,0xA8,0x1F,0xD3,0x00,0x8D, _
0x14,0xA1,0x00,0xC8,0xDA,0x02,0x81,0xCF,0xD9,0xF1, 0xDB,0x30,0xA4,0xA6)

gosub sendtodisplay ; send 4 blank lines to clear display
let displaybank = 0 ; flag rows 0-3 for display
hi2cout 0x80,(0xAF) ; turn display on


main:
i2cslave 0xAA, i2cfast, i2cbyte
readi2c 0x08,(b8) ; Read volt from eeprom
readi2c 0x09,(b9) ; Read volt from eeprom
pause 10
readi2c 0x2c,(b10) ; Read SOC from eeprom
readi2c 0x2d,(b11) ; Read SOC from eeprom
debug ; Show result

hi2csetup i2cmaster,$78,i2cfast,i2cbyte;

; Insert your programme code here and then poke 28-91 with message to be displayed
;data to send to display (4 * 16)

poke 28," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "
poke 44," "," ","V","o","l","t"," " ; see if b18 is incremented and what is displayed on screen
bTmp = Volt / 1000 // 10 + "0" : Poke 51, bTmp
bTmp = Volt / 100 // 10 + "0" : Poke 52, bTmp
bTmp = Volt / 10 // 10 + "0" : Poke 53, bTmp
bTmp = Volt // 10 + "0" : Poke 54, bTmp
poke 55," "," "," "," "," "
poke 60," "," ","S","o","c"," "," "
bTmp = SOC / 1000 // 10 + "0" : Poke 67, bTmp
bTmp = SOC / 100 // 10 + "0" : Poke 68, bTmp
bTmp = SOC / 10 // 10 + "0" : Poke 69, bTmp
bTmp = SOC // 10 + "0" : Poke 70, bTmp
poke 71," "," "," "," "," "
poke 76," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "

displaybank = 1 - displaybank ; toggle lines to display
gosub sendtodisplay ; load message to display memory and point display at it

; Insert any further code you require here





goto main

sendtodisplay: ; sends characters in memory locations 28-91 to the display
for counter = 28 to 91
PEEK counter, fontlookup ; load character to output
select case fontlookup
case 48 to 57 ; 0-9
fontlookup = fontlookup - 48 * 5
case 65 to 90 ; A-Z
fontlookup = fontlookup -65 * 5 + 50
case 97 to 122 ; a-z output as A-Z
fontlookup = fontlookup - 97 * 5 + 50

else
fontlookup = 244 ; all other characters will display a blank
endselect
hi2cout 0x40,(0) ; one blank column
for subcounter = 0 to 4
read fontlookup, pixels
hi2cout 0x40,(pixels) ; followed by 5 columns per character
fontlookup = fontlookup + 1
next subcounter
hi2cout 0x40,(0,0) ; two blank columns
next counter ; this completes the 8x8 character output
If displaybank = 0 then
hi2cout 0x80,(0x40) ; point display to lines 0-3 of display memory
else hi2cout 0x80,(0x60) ; point display to lines 4-7 of display memory
Endif
return
 

hippy

Technical Support
Staff member
Why did setting up the master again work to change which slave it was looking at???? I was hoping you could just change the slave address then read it but if you try this then it does nothing on the OEL.
The I2CSLAVE command is an older, deprecated, equivalent of HI2CSETUP I2CMASTER.

So what you were doing was an HI2CSETUP to talk to the OLED, an HI2CSETUP ( via I2CSLAVE ) to read the data, but not doing another HI2CSETUP before talking to the OLED again - Anything sent to the OLED ended up being sent to the sensor selected by the last HI2CSETUP, not the actual OLED.

Adding the additional HI2CSETUP means subsequent I2C output actually goes to the OLED, as desired.
 

tecnition_ted

New Member
Lot to learn! I was hoping that I could just keep changing the address then talk to each device. I'll add an HI2CSETUP before talking to each device.
I'm looking up SMBUS as a lot of battery I.C's use this. I see it is comparable with i2c but may need changes including speed.

I still haven't added any extra characters yet so will do that too along with sending the information to a serial screen. following rule one though "change only one thing and see if it works change more get confused"

Thank you for your help Hippy
 

tecnition_ted

New Member
Hi don't understand this one at all
Ok so I've added a serial oel AXE133Y I thought this would be easy to add to the OEL program as we would just need to send the same information to the Serial screen as the oel screen or there about's

I tried a simple test and it failed i have no understanding to why.

I placed the serial test code which works on its own (its not quite right for clearing the screen but wanted a quick solution) at the start of the battery reader code I thought the serial screen would print the information then be ignored for the rest of the code. What happens is if the code is run on its own it works when added to the top of the oel code the serial screen keeps showing the picaxe . com information and you can see a faint flicker as the i2c oel is updated. I have nothing but the serial screen attached to C.0

This is the code attached to the i2c oel code above

Code:
[
Code:
;new code serial LCD
low c.0                    ; Initialize LCD output
    pause 500                ; Wait for LCD to initialize

    serout c.0, n2400, ( 254, $80 )        ; First line of display
    serout c.0, n2400, ( "                " )    ; Display "Temperature"
   
    serout c.0, n2400, ( 254, $80 )        ; First line of display
    serout c.0, n2400, ( "Temperature" )    ; Display "Temperature"
    serout c.0, n2400, ( 254, $C0 )        ; Second line of display
    serout c.0, n2400, ( "                " )    ; Display the temperature
    serout c.0, n2400, ( 254, $C0 )        ; Second line of display
    serout c.0, n2400, ( "mmmmm" )    ; Display the temperature
   
   



;i2c code (not complete)
symbol counter = w0
symbol subcounter = b2
symbol fontlookup = b3
symbol pixels = b4
symbol displaybank = b5
symbol Volt = w4
symbol SOC = w5
symbol timetillemptymins = w6
symbol bTmp = w7



; save Font codes in EEPROM
 
Last edited by a moderator:

hippy

Technical Support
Staff member
On an 08M2 the C.0 pin is the Download Serial Out. That will send 'random data' out of C.0 as a new program is downloaded which will also go to the AXE133 and this may confuse the AXE133, may stop it working.

Things may work if you turn everything off after downloading a program, wait a while, then turn everything back on.

It would be best to connect the AXE133 to another pin of the 08M2.
 

AllyCat

Senior Member
Hi,
On an 08M2 the C.0 pin is the Download Serial Out. ...
Yes, that was my "guess" at the issue, but perhaps we need the OP to confirm he is using an 08M2 (since he appended his original question to an "old" thread).

On that assumption, I looked through his code above (please use [ code] .. [ /code] tags) for any SERTXDs. I didn't see any, but there was a DEBUG command that could create even more havok in the AXE133. :(

Cheers, Alan.
 

mrm

Member
I got a very cheap I2C display (<£3) from eBay, intending to use it with an 08M2 but couldn't find much information about it. After a few hours research and some experimenting, I managed to get the display working and thought it might be helpful to share the results.



I started with the excellent information in this thread, which is for a different display but with much in common: http://www.picaxeforum.co.uk/archive/index.php/t-23134.html I also got inspiration for the font lookup from this thread: http://www.picaxeforum.co.uk/entry.php?30-Notes-behind-Magic-Morse

This is the display I purchased: http://www.ebay.co.uk/itm/162337263365?_trksid=p2057872.m2749.l2649&ssPageName=STRK:MEBIDX:IT

Although it says its 128 * 64, the display is actually 128 * 32 but the display memory holds 128 * 64. As each byte is written to the display memory it appears on screen so the display builds as it is sent. To avoid this, you can point the display to start at a specific memory location and as there is exactly enough memory for 2 screens of data you can write the message to the unused block and then point the display to it for instant update.

I needed to design a font to use with the display so I used excel to play around with different options. I settled on an 8 * 8 block for each character as this fitted very well with the display dimensions, giving four rows of sixteen characters. This is the spreadsheet I used:
https://www.dropbox.com/s/vw8mgrwu5hhi9dj/OLED Font.xls?dl=0
It converts the pixels into the eeprom commands needed to load the font into the 08M2. I only needed numbers and upper case characters (the programme will display any lower case characters as upper case). It would be straightforward to add any other characters that may be needed.

To send a message to the display you poke the required characters to memory locations 28 to 91 and then the programme looks up the font data and sends it to the display. When all the data has been sent, the display is pointed to the start of the latest message in display memory.

The code to drive the display is shown below. In this example the main programme just loads a message to memory locations 28 - 91, calls the sendtodisplay subroutine and then loops. As it only uses 413 bytes there is plenty of room for other code which could create its own messages.

Code:
symbol counter = w0
symbol subcounter = b2
symbol fontlookup = b3
symbol pixels = b4
symbol displaybank = b5

; save Font codes in EEPROM

eeprom 0,(124,130,130,130,124)       ; 0 (ASCII 48)
eeprom 5,(136,132,254,128,128)       ; 1
eeprom 10,(196,162,162,146,140)       ; 2
eeprom 15,(68,130,146,146,108)       ; 3
eeprom 20,(48,40,36,254,32)               ; 4
eeprom 25,(110,138,138,138,114)       ; 5
eeprom 30,(124,146,146,146,100)       ; 6
eeprom 35,(2,2,2,2,254)                   ; 7
eeprom 40,(108,146,146,146,108)       ; 8
eeprom 45,(30,18,18,18,254)               ; 9 (ASCII 57)
eeprom 50,(254,18,18,18,254)       ; A (ASCII 65)
eeprom 55,(254,146,146,146,108)       ; B
eeprom 60,(254,130,130,130,130)       ; C
eeprom 65,(254,130,130,68,56)       ; D
eeprom 70,(254,146,146,146,130)       ; E
eeprom 75,(254,18,18,18,2)           ; F
eeprom 80,(254,130,130,146,242)       ; G
eeprom 85,(254,16,16,16,254)       ; H
eeprom 90,(130,130,254,130,130)       ; I
eeprom 95,(226,130,254,2,2)               ; J
eeprom 100,(254,16,40,68,130)       ; K
eeprom 105,(254,128,128,128,128)       ; L
eeprom 110,(254,2,254,2,254)       ; M
eeprom 115,(254,4,56,64,254)       ; N
eeprom 120,(254,130,130,130,254)       ; O
eeprom 125,(254,18,18,18,12)       ; P
eeprom 130,(124,130,162,66,188)       ; Q
eeprom 135,(254,18,50,82,140)       ; R
eeprom 140,(222,146,146,146,246)       ; S
eeprom 145,(2,2,254,2,2)           ; T
eeprom 150,(126,128,128,128,126)       ; U
eeprom 155,(30,96,128,96,30)       ; V
eeprom 160,(254,128,254,128,254)       ; W
eeprom 165,(198,40,16,40,198)       ; X
eeprom 170,(6,8,240,8,6)           ; Y
eeprom 175,(194,162,146,138,134)       ; Z (ASCII 90)


initialise:
; initialise i2c for display (ID 0x78) and then send power up instructions
                   
hi2csetup i2cmaster,%01111000,i2cfast,i2cbyte   
hi2cout 0x80,(0xAE,0x00,0x00,0xB0,0x20,0x00,0xD5,0x80,0xA8,0x1F,0xD3,0x00,0x8D, _
0x14,0xA1,0x00,0xC8,0xDA,0x02,0x81,0xCF,0xD9,0xF1, 0xDB,0x30,0xA4,0xA6)

gosub sendtodisplay                    ; send 4 blank lines to clear display
let displaybank = 0                    ; flag rows 0-3 for display
hi2cout 0x80,(0xAF)                    ; turn display on


main:
; Insert your programme code here and then poke 28-91 with message to be displayed

poke 28," ","T","H","I","S"," ","I","S"," ","A"," ","T","E","S","T"," ";data to send to display (4 * 16)
poke 44,"O","F"," ","T","H","E"," ","O","U","T","P","U","T"," ","T","O"
poke 60,"T","H","E"," ","O","L","E","D"," ","D","I","S","P","L","A","Y"
poke 76,"F","R","O","M"," ","A","N"," ","0","8","M","2"," ","P","I","C"

displaybank = 1 - displaybank        ; toggle lines to display
gosub sendtodisplay                    ; load message to display memory and point display at it

; Insert any further code you require here

goto main

sendtodisplay:                                                ; sends characters in memory locations 28-91 to the display
for counter = 28 to 91
    PEEK counter, fontlookup                        ; load character to output
    select case fontlookup
        case 48 to 57                            ; 0-9
            fontlookup = fontlookup - 48 * 5
        case 65 to 90                            ; A-Z
            fontlookup = fontlookup -65 * 5 + 50
        case 97 to 122                            ; a-z output as A-Z
            fontlookup = fontlookup - 97 * 5 + 50
        else
            fontlookup = 244    ; all other characters will display a blank
    endselect                   
    hi2cout 0x40,(0)            ; one blank column
    for subcounter = 0 to 4
        read fontlookup, pixels       
        hi2cout 0x40,(pixels)        ; followed by 5 columns per character
        fontlookup = fontlookup + 1
    next subcounter
    hi2cout 0x40,(0,0)            ; two blank columns
next counter                    ; this completes the 8x8 character output
If displaybank = 0 then
    hi2cout 0x80,(0x40)            ; point display to lines 0-3 of display memory
    else hi2cout 0x80,(0x60)        ; point display to lines 4-7 of display memory
Endif
return
This is my first attempt at Picaxe programming, so any pointers to improve the way I've gone about it would be greatly appreciated and I hope it is of some use!
Interesting post and a pretty good first attempt.

A similar attempt to use a picaxe 14M2 or 08M2 as a serial display driver for an oled worked amazingly well apart from the slow update rate. It will be interesting to revisit the problem using your technique.
 

tecnition_ted

New Member
Hi Hippy and guys,
Yes I am using a 20M2 it is at the moment doing nothing but run the i2c display and the attempted serial display.
I am thinking that eventually it would be good to maybe use an 08M2 just to run as the slave oel driver for the oel display but it would be interesting if I can make a one for all battery reader.

The Texas Investments BQ series of chips are very good and do keep to the same addresses on most for SOC and Volts so making this project would be ideal for E bikes, Robots and anything else that uses a battery. TI also have in the same range a lot of charge ic's which are programmed in the same manor.

There is little out there on u tube about reading the BQ i2c chips in a way that a total beginner can understand and unless you can stump up 180 notes for an EV2400 you cant without any knowledge read or program these chips.

Any way any ideas?
The serial LCD should just display Temperature & mmmm without any interaction with the oel program. The code works on its own on the same 20m2 the oel is attached to if the oel code is removed but when added to the top of the code it docent work or even clear the built in picaxe .com logo

I don't understand why, as if there was code or debug interference then at lest the picaxe logo would be removed???
 

tecnition_ted

New Member
I have attached a photo of the board at the moment. The led's show power green red TX and yellow RX
The OEL is not showing any SOC as the BQ chip cannot handle the battery pack capacity so I'm going to change it for an update chip.
At the moment the pack is a 5 volt out, power bank 35ah hoping to take it to 105ah or more for a solar experiment.
 

Attachments

hippy

Technical Support
Staff member
The code works on its own on the same 20m2 the oel is attached to if the oel code is removed but when added to the top of the code it docent work or even clear the built in picaxe .com logo
That's very odd. If it works by itself it should also work with code added after it. The AXE133 should have been initialised and written to exactly the same.

The only thing I can think is that the AXE133 is somehow being reset so it goes back to its initial display, or it's being instructed to display the "picaxe.com" and URL messages which are in the AXE133 Eeprom.

I would add a PAUSE 60000 after the AXE133 initial display code. That will show if the display is being initialised and written to for a minute after starting. If it then reverts to "picaxe.com" then it's working but one of the two above is happening.

If you can post your full code that may reveal what is going on.

I would also double check the board to make sure that the AXE133 signals are not accidentally shorting to other components which use the same tracks. Activating the components to the right of the AXE133 connector could be affecting what the AXE133 sees or does.
 

tecnition_ted

New Member
Will do.
I also have another thing happening, I am trying to read SM bus and when I change the read address to 0x17 I get an error but if I change it one number up or down all is ok?

Sorry for all the questions this week has been only time I've had to concentrate on this
 

Attachments

tecnition_ted

New Member
ok here is the code for the serial without SMB mod
When the delay was added the display remained on picaxe.com screen nothing changed for half a second then the i2c program resumed as normal
Hope the code is displayed correctly as i looked at other post's and code in brackets was the correct way to list.

Code:
;new code serial LCD
low c.0                    ; Initialize LCD output
    pause 500                ; Wait for LCD to initialize

    serout c.0, n2400, ( 254, $80 )        ; First line of display
    serout c.0, n2400, ( "                " )    ; Display "Temperature"
   
    serout c.0, n2400, ( 254, $80 )        ; First line of display
    serout c.0, n2400, ( "Temperature" )    ; Display "Temperature"
    serout c.0, n2400, ( 254, $C0 )        ; Second line of display
    serout c.0, n2400, ( "                " )    ; Display the temperature
    serout c.0, n2400, ( 254, $C0 )        ; Second line of display
    serout c.0, n2400, ( "mmmmm" )    ; Display the temperature
pause 60000 ;added delay to see if information is displayed

symbol counter = w0
symbol subcounter = b2
symbol fontlookup = b3
symbol pixels = b4
symbol displaybank = b5
symbol Volt = w4
symbol SOC = w5
symbol timetillemptymins = w6
symbol bTmp = w7



; save Font codes in EEPROM

eeprom 0,(124,130,130,130,124)       ; 0 (ASCII 48)
eeprom 5,(136,132,254,128,128)       ; 1
eeprom 10,(196,162,162,146,140)       ; 2
eeprom 15,(68,130,146,146,108)       ; 3
eeprom 20,(48,40,36,254,32)               ; 4
eeprom 25,(110,138,138,138,114)       ; 5
eeprom 30,(124,146,146,146,100)       ; 6
eeprom 35,(2,2,2,2,254)                   ; 7
eeprom 40,(108,146,146,146,108)       ; 8
eeprom 45,(30,18,18,18,254)       ; 9 (ASCII 57)
eeprom 50,(254,18,18,18,254)       ; A (ASCII 65)
eeprom 55,(254,146,146,146,108)       ; B
eeprom 60,(254,130,130,130,130)       ; C
eeprom 65,(254,130,130,68,56)       ; D
eeprom 70,(254,146,146,146,130)       ; E
eeprom 75,(254,18,18,18,2)           ; F
eeprom 80,(254,130,130,146,242)       ; G
eeprom 85,(254,16,16,16,254)       ; H
eeprom 90,(130,130,254,130,130)       ; I
eeprom 95,(226,130,254,2,2)       ; J
eeprom 100,(254,16,40,68,130)       ; K
eeprom 105,(254,128,128,128,128)       ; L
eeprom 110,(254,2,254,2,254)       ; M
eeprom 115,(254,4,56,64,254)       ; N
eeprom 120,(254,130,130,130,254)       ; O
eeprom 125,(254,18,18,18,12)       ; P
eeprom 130,(124,130,162,66,188)       ; Q
eeprom 135,(254,18,50,82,140)       ; R
eeprom 140,(222,146,146,146,246)       ; S
eeprom 145,(2,2,254,2,2)           ; T
eeprom 150,(126,128,128,128,126)       ; U
eeprom 155,(30,96,128,96,30)       ; V
eeprom 160,(254,128,254,128,254)       ; W
eeprom 165,(198,40,16,40,198)       ; X
eeprom 170,(6,8,240,8,6)           ; Y
eeprom 175,(194,162,146,138,134)       ; Z (ASCII 90)





initialise:
; initialise i2c for display (ID 0x78) and then send power up instructions
                    
hi2csetup i2cmaster,$78,i2cfast,i2cbyte    
hi2cout 0x80,(0xAE,0x00,0x00,0xB0,0x20,0x00,0xD5,0x80,0xA8,0x1F,0xD3,0x00,0x8D, _
0x14,0xA1,0x00,0xC8,0xDA,0x02,0x81,0xCF,0xD9,0xF1, 0xDB,0x30,0xA4,0xA6)

gosub sendtodisplay             ; send 4 blank lines to clear display
let displaybank = 0             ; flag rows 0-3 for display
hi2cout 0x80,(0xAF)             ; turn display on


main:
i2cslave 0xAA, i2cfast, i2cbyte                
readi2c 0x08,(b8)                ; Read volt from eeprom
readi2c 0x09,(b9)                ; Read volt from eeprom
pause 10
readi2c 0x2c,(b10)            ; Read SOC from eeprom
readi2c 0x2d,(b11)            ; Read SOC from eeprom
pause 10
readi2c 0x16,(b12)            ; Read time till empty mins from eeprom
readi2c 0x17,(b13)            ; Read time till empty mins eeprom
debug                        ; Show result

hi2csetup i2cmaster,$78,i2cfast,i2cbyte; 

; Insert your programme code here and then poke 28-91 with message to be displayed
;data to send to display (4 * 16)

poke 28,"T","i","m","e"," ","l","e","f","t"," "
bTmp = timetillemptymins / 1000 // 10 + "0" : Poke 38, bTmp
bTmp = timetillemptymins / 100  // 10 + "0" : Poke 39, bTmp
bTmp = timetillemptymins / 10   // 10 + "0" : Poke 40, bTmp
bTmp = timetillemptymins        // 10 + "0" : Poke 41, bTmp
poke 42," "," "
poke 44," "," ","V","o","l","t"," " ; 
bTmp = Volt / 1000 // 10 + "0" : Poke 51, bTmp
bTmp = Volt / 100  // 10 + "0" : Poke 52, bTmp
bTmp = Volt / 10   // 10 + "0" : Poke 53, bTmp
bTmp = Volt        // 10 + "0" : Poke 54, bTmp
poke 55," "," "," "," "," "
poke 60," "," ","S","o","c"," "," "
bTmp = SOC / 1000 // 10 + "0" : Poke 67, bTmp
bTmp = SOC / 100  // 10 + "0" : Poke 68, bTmp
bTmp = SOC / 10   // 10 + "0" : Poke 69, bTmp
bTmp = SOC        // 10 + "0" : Poke 70, bTmp
poke 71," "," "," "," "," "
poke 76," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "

displaybank = 1 - displaybank         ; toggle lines to display
gosub sendtodisplay             ; load message to display memory and point display at it

; Insert any further code you require here
    




goto main

sendtodisplay:                 ; sends characters in memory locations 28-91 to the display
for counter = 28 to 91
    PEEK counter, fontlookup     ; load character to output
    select case fontlookup
        case 48 to 57                            ; 0-9
            fontlookup = fontlookup - 48 * 5
        case 65 to 90                            ; A-Z
            fontlookup = fontlookup -65 * 5 + 50
        case 97 to 122                            ; a-z output as A-Z
            fontlookup = fontlookup - 97 * 5 + 50
        
        else
            fontlookup = 244     ; all other characters will display a blank
    endselect                    
    hi2cout 0x40,(0)             ; one blank column
    for subcounter = 0 to 4
        read fontlookup, pixels        
        hi2cout 0x40,(pixels)     ; followed by 5 columns per character
        fontlookup = fontlookup + 1
    next subcounter
    hi2cout 0x40,(0,0)         ; two blank columns
next counter                 ; this completes the 8x8 character output
If displaybank = 0 then
    hi2cout 0x80,(0x40)         ; point display to lines 0-3 of display memory
    else hi2cout 0x80,(0x60)     ; point display to lines 4-7 of display memory
Endif
return
 

tecnition_ted

New Member
Checked both the vero and the picaxe PCB for shorts none found, tested using just screen code on same setup and works ok without the i2c code. just the i2c display is then as expected blank.
 

hippy

Technical Support
Staff member
I am trying to read SM bus and when I change the read address to 0x17 I get an error but if I change it one number up or down all is ok?
0x17 isn't a valid I2C Device Address for a PICAXE. The PICAXE uses 8-bit Device Addresses with the least significant bit as zero.

If that 0x17 is a 7-bit Device Address it needs to be adjusted, by multiplying by two ...

7-bit 0x17 becomes 8-bit 0x2E - So try with 0x2E ( or $2E ).
 

hippy

Technical Support
Staff member
Can you provide details of what device you are trying to access, provide a link to its datasheet or example code, what the code is you are using which delivers gibberish ?

That should help clarify what the Device Address should be and may allow how data should be read to be determined.
 

tecnition_ted

New Member
Hi Hippy
Should this moved to another posting as although it is connected to the above code it is more about reading SM bus? I still cannot get the serial screen to work when the i2c code is present if it is removed the screen prints the test text.

In regards to the Device the data sheet is too big to attach for the Ti BQ40z50-R1 here is the link to the data sheet http://www.ti.com/lit/ds/symlink/bq40z50-r1.pdf
and the technical reference manual.

The code is as above with a slow i2c bus.

Code:
;low c.0                    ; Initialise LCD output
    ;pause 500                ; Wait for LCD to initialise

    ;serout c.0, n2400, ( 254, $80 )        ; First line of display
    ;serout c.0, n2400, ( "                " )    ; Display "Temperature"
    
    ;serout c.0, n2400, ( 254, $80 )        ; First line of display
    ;serout c.0, n2400, ( "Temperature" )    ; Display "Temperature"
    ;serout c.0, n2400, ( 254, $C0 )        ; Second line of display
    ;serout c.0, n2400, ( "                " )    ; Display the temperature
    ;serout c.0, n2400, ( 254, $C0 )        ; Second line of display
    ;serout c.0, n2400, ( "mmmmm" )    ; Display the temperature
    
    




symbol counter = w0
symbol subcounter = b2
symbol fontlookup = b3
symbol pixels = b4
symbol displaybank = b5
symbol Volt = w4
symbol SOC = w5
symbol timetillemptymins = w6
symbol bTmp = w7



; save Font codes in EEPROM

eeprom 0,(124,130,130,130,124)       ; 0 (ASCII 48)
eeprom 5,(136,132,254,128,128)       ; 1
eeprom 10,(196,162,162,146,140)       ; 2
eeprom 15,(68,130,146,146,108)       ; 3
eeprom 20,(48,40,36,254,32)               ; 4
eeprom 25,(110,138,138,138,114)       ; 5
eeprom 30,(124,146,146,146,100)       ; 6
eeprom 35,(2,2,2,2,254)                   ; 7
eeprom 40,(108,146,146,146,108)       ; 8
eeprom 45,(30,18,18,18,254)       ; 9 (ASCII 57)
eeprom 50,(254,18,18,18,254)       ; A (ASCII 65)
eeprom 55,(254,146,146,146,108)       ; B
eeprom 60,(254,130,130,130,130)       ; C
eeprom 65,(254,130,130,68,56)       ; D
eeprom 70,(254,146,146,146,130)       ; E
eeprom 75,(254,18,18,18,2)           ; F
eeprom 80,(254,130,130,146,242)       ; G
eeprom 85,(254,16,16,16,254)       ; H
eeprom 90,(130,130,254,130,130)       ; I
eeprom 95,(226,130,254,2,2)       ; J
eeprom 100,(254,16,40,68,130)       ; K
eeprom 105,(254,128,128,128,128)       ; L
eeprom 110,(254,2,254,2,254)       ; M
eeprom 115,(254,4,56,64,254)       ; N
eeprom 120,(254,130,130,130,254)       ; O
eeprom 125,(254,18,18,18,12)       ; P
eeprom 130,(124,130,162,66,188)       ; Q
eeprom 135,(254,18,50,82,140)       ; R
eeprom 140,(222,146,146,146,246)       ; S
eeprom 145,(2,2,254,2,2)           ; T
eeprom 150,(126,128,128,128,126)       ; U
eeprom 155,(30,96,128,96,30)       ; V
eeprom 160,(254,128,254,128,254)       ; W
eeprom 165,(198,40,16,40,198)       ; X
eeprom 170,(6,8,240,8,6)           ; Y
eeprom 175,(194,162,146,138,134)       ; Z (ASCII 90)





initialise:
; initialise i2c for display (ID 0x78) and then send power up instructions
                    
hi2csetup i2cmaster,$78,i2cfast,i2cbyte    
hi2cout 0x80,(0xAE,0x00,0x00,0xB0,0x20,0x00,0xD5,0x80,0xA8,0x1F,0xD3,0x00,0x8D, _
0x14,0xA1,0x00,0xC8,0xDA,0x02,0x81,0xCF,0xD9,0xF1, 0xDB,0x30,0xA4,0xA6)

gosub sendtodisplay             ; send 4 blank lines to clear display
let displaybank = 0             ; flag rows 0-3 for display
hi2cout 0x80,(0xAF)             ; turn display on


main:
i2cslave 0x16, i2cslow, i2cbyte                
readi2c 0x08,(b8)                ; Read volt from eeprom
readi2c 0x09,(b9)                ; Read volt from eeprom

readi2c 0x0F,(b10)            ; Read SOC from eeprom
readi2c 0x10,(b11)            ; Read SOC from eeprom

readi2c 0x06,(b12)            ; Read time till empty mins from eeprom
readi2c 0x17,(b13)            ; Read time till empty mins eeprom
debug                        ; Show result


hi2csetup i2cmaster,$78,i2cfast,i2cbyte; 

; Insert your programme code here and then poke 28-91 with message to be displayed
;data to send to display (4 * 16)

poke 28,"T","i","m","e"," ","l","e","f","t"," "
bTmp = timetillemptymins / 1000 // 10 + "0" : Poke 38, bTmp
bTmp = timetillemptymins / 100  // 10 + "0" : Poke 39, bTmp
bTmp = timetillemptymins / 10   // 10 + "0" : Poke 40, bTmp
bTmp = timetillemptymins        // 10 + "0" : Poke 41, bTmp
poke 42," "," "
poke 44," "," ","V","o","l","t"," " ; 
bTmp = Volt / 1000 // 10 + "0" : Poke 51, bTmp
bTmp = Volt / 100  // 10 + "0" : Poke 52, bTmp
bTmp = Volt / 10   // 10 + "0" : Poke 53, bTmp
bTmp = Volt        // 10 + "0" : Poke 54, bTmp
poke 55," "," "," "," "," "
poke 60," "," ","S","o","c"," "," "
bTmp = SOC / 1000 // 10 + "0" : Poke 67, bTmp
bTmp = SOC / 100  // 10 + "0" : Poke 68, bTmp
bTmp = SOC / 10   // 10 + "0" : Poke 69, bTmp
bTmp = SOC        // 10 + "0" : Poke 70, bTmp
poke 71," "," "," "," "," "
poke 76," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "

displaybank = 1 - displaybank         ; toggle lines to display
gosub sendtodisplay             ; load message to display memory and point display at it

; Insert any further code you require here
    




goto main

sendtodisplay:                 ; sends characters in memory locations 28-91 to the display
for counter = 28 to 91
    PEEK counter, fontlookup     ; load character to output
    select case fontlookup
        case 48 to 57                            ; 0-9
            fontlookup = fontlookup - 48 * 5
        case 65 to 90                            ; A-Z
            fontlookup = fontlookup -65 * 5 + 50
        case 97 to 122                            ; a-z output as A-Z
            fontlookup = fontlookup - 97 * 5 + 50
        
        else
            fontlookup = 244     ; all other characters will display a blank
    endselect                    
    hi2cout 0x40,(0)             ; one blank column
    for subcounter = 0 to 4
        read fontlookup, pixels        
        hi2cout 0x40,(pixels)     ; followed by 5 columns per character
        fontlookup = fontlookup + 1
    next subcounter
    hi2cout 0x40,(0,0)         ; two blank columns
next counter                 ; this completes the 8x8 character output
If displaybank = 0 then
    hi2cout 0x80,(0x40)         ; point display to lines 0-3 of display memory
    else hi2cout 0x80,(0x60)     ; point display to lines 4-7 of display memory
Endif
return
 

Attachments

hippy

Technical Support
Staff member
Should this moved to another posting as although it is connected to the above code it is more about reading SM bus?
It is probably best to keep to this thread for now.

When the delay was added the display remained on picaxe.com screen nothing changed for half a second then the i2c program resumed as normal
That's very odd because, if the AXE133 code works when there's no I2C code following it, it should also work when that I2C code is present with a PAUSE 60000 between the two. The AXE133 should be initialised, then the initial display should be shown for a full minute, not just a half second.

For the first minute after download or reset the PICAXE should behave as if the I2C code isn't there, even if it is.

Thanks. I'll take a look at that.
 

hippy

Technical Support
Staff member
That bq40z50-R1 seems to be one of the most complicated devices I have ever encountered. I am not entirely convinced it will work with a PICAXE.

When something is labelled SMbus, they usually mean it's I2C with a little bit extra, which can be used as if I2C with that extra simply ignored. I am not sure that is the case for this device.

For a start, Page 35 - "The SMBus clock and data lines have internal pulldown. When the gas gauge senses that both lines are low (such as during removal of the pack), the device performs auto-offset calibration and then goes into SLEEP mode to conserve power".

That seems to be at odds with I2C which is an open-collector bus with pull-ups. Both lines low is a feature of I2C communications, and I can't exactly understand how it couldn't be for SMbus, though I am not familiar with that.

There do seem to be some 'SBS' commands which look like they could be coerced into I2C commands so I would disconnect the LCD and everything else from the I2C bus except the bq40z50-R1 and try this, see if it produces any sensible output -
Code:
#Picaxe 20M2
#Terminal 4800
#No_Data

Do
  Pause 3000
  SerTxd( CR, LF )

  HI2cSetup I2CMASTER, 0x16, I2CSLOW, I2CBYTE

  HI2cIn 0x20,(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17,b18,b19,b20,b21)
  SerTxd("Manufacturer=") : b0=21 : Gosub ShowText

  HI2cIn 0x21,(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16,b17,b18,b19,b20,b21)
  SerTxd("Device=") : b0=21: Gosub ShowText

  HI2cIn 0x22,(b1,b2,b3,b4,b5)
  SerTxd("Chemistry=") : b0=5: Gosub ShowText

  ; Day + Month*32 + (Year–1980)*512
  HI2cIn 0x18,(b1,b0)
  w1 = w0 & 31
  w2 = w0 / 32 & 15
  w3 = w0 / 512 + 1980
  SerTxd("Date=",#w3,"-",#w2,"-",#w1)
  w0 = b0 * 256 + b1
  w1 = w0 & 31
  w2 = w0 / 32 & 15
  w3 = w0 / 512 + 1980
  SerTxd(" or ",#w3,"-",#w2,"-",#w1, CR, LF)

Loop

ShowText:
  bPtr = 1
  Do
    b27 = @bPtrInc
    If b27 >= 0x20 And b27 <= 0x7E Then
      SerTxd( b27 )
    Else
      SerTxd( "<", #b27, ">" )
    End If
  Loop Until bPtr > b0
  SerTxd( CR, LF )
  Return
 

AllyCat

Senior Member
Hi,
For a start, Page 35 - "The SMBus clock and data lines have internal pulldown.
Page 6 shows the internal pull-down resistors on the "SMBus" as 1 Mohms, so not likely to significantly affect the normal I2C pullup impedances and voltages.

From the description you quote, I guess the idea is that when the device is "unplugged" (disconnected from the batteries it's monitoring) it recognises that there are no I2C pullups and performs a calibration and power-down process.

Cheers, Alan.
 

hippy

Technical Support
Staff member
Thanks for the pull-down info. I found this long thread which deals with a very similar chip and it seems that it is basically I2C so I am more confident my code above should deliver something meaningful if wired correctly and enabled -

https://community.particle.io/t/using-i2c-for-smbus-device-communications/8980

For the 21 bytes read as text (S20+1 in the datasheet), it appears the first byte may be the actual length of the string that's being returned. Whatever it prints out should clarify that which only leaves endianess. That should be solved from reference to the date read, the thread or reading a 16-bit or 32-bit value when we know which bits should be which, once we can read the text data reliably.

So communications, at least reading, may not be too difficult. If the Sn+1 strings aren't fixed length but variable that's a challenge but should be doable ...
Code:
HI2cIn 0x20,(b0)
Select Case b0
  Case 1 : HI2cIn 0x20,(b0,b1)
  Case 2 : HI2cIn 0x20,(b0,b1,b2)
 

tecnition_ted

New Member
Hi Hippy
Its a pain in the butt of a chip!

The data fed back was
Manufacturer=<255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255>
Device=<255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255><255>
Chemistry=<255><255><255><255><255>
Date=2107-15-31 or 2107-15-31

I have attached the BQ studio information of this area of the memory.

is it looking like the SM bus is not compatible?
 

Attachments

tecnition_ted

New Member
tecnition_ted said:
When the delay was added the display remained on picaxe.com screen nothing changed for half a second then the i2c program resumed as normal
That's very odd because, if the AXE133 code works when there's no I2C code following it, it should also work when that I2C code is present with a PAUSE 60000 between the two. The AXE133 should be initialised, then the initial display should be shown for a full minute, not just a half second.

For the first minute after download or reset the PICAXE should behave as if the I2C code isn't there, even if it is.

That's just what I thought and why I just added a test at the beginning of the code to check it worked. I would have thought it might have changed after the delay but displayed correctly beforehand. Do you think there may be a memory location clash?
 

hippy

Technical Support
Staff member
Manufacturer=<255><255><255>...

Those 255's (0xFF's) usually indicate the I2C device is not responding, the device is not enabled, Device Address is wrong, I2C bus signals not connected or crossed-over.

The pointed to thread suggests I2C is possible, and should therefore, I would have thought, also work with a PICAXE. There was some discussion on repeated-starts and it can be tricky if an I2C device doesn't accept the traditional I2C protocol. That may require bit-banging I2C to make it work.

At least we do have something which demonstrates it does respond and what data should be returned. But that doesn't really help with why the PICAXE doesn't work.

You can run the following which will try to identify if there is anything found which responds other than with 0xFF's ...
Code:
#Picaxe 20M2
#Terminal 4800
#No_Data

Do
  Pause 3000
  SerTxd("Scanning...",CR,LF)
  For b7 = 0x10 To 0xEE Step 2
    HI2cSetup I2CMASTER, b7, I2CSLOW, I2CBYTE
    HI2cIn 0x18,(b1,b0)
    If w0 <> $FFFF Then
      b1 = b7 / 16 + "0" : If b1 > "9" Then : b1 = b1 + 7 : End If
      b0 = b7 & 15 + "0" : If b0 > "9" Then : b0 = b0 + 7 : End If
      SerTxd( "Found Device Address 0x", b1, b0, CR, LF )
    End If
  Next
Loop
 

tecnition_ted

New Member
Code running i'll get back when it finds something. i2c screen is unplugged so what it finds will be BQ chip only

Any ideas about the serial screen not operating? bit of a mystery
 

hippy

Technical Support
Staff member
Apart from any wiring or connection issues which would prevent it from working with anything, it could be that the HI2CIN isn't compatible with what the chip is expecting.

"HI2CIN 0xAA, (b0)" will send something like -

<start> 0x16 0xAA <stop> <start> 0x17 <read> <stop>

The chip may be expecting -

<start> 0x16 0xAA <read> <stop>

That can only be generated by bit-banging the I2C bus.
 

tecnition_ted

New Member
I got to 40900 after two days without finding anything I think it may be time to give up and try an UNO or something. unfortunately SMB is quite common in battery BMS. Wonder if there is any way of making a converter picaxe i2c or serial to SMB with extra components??
 
Top