Write to non Picaxe LCD Display

Michael V

Senior Member
Hi All,

I am attempting to build a device that, based upon data from a pressure transducer, will record the time certain events took place. These are pressure spikes to be recorded in an eprom chip, and displayed on a Serial LCD, and output in serial to an attached computer using the sertxd command. An event datalogger, if you like, a little different to the AXE110 which is scheduled.

I have at long last programmed my 18X chip to program the DS1307 chip with the time, using the Datalogger wizard. I can transmit the time of the event and the event data using SERTXD.

Now the tricky bit. Instead of using the AXE033 i have been able to lay my hands on a Modtronix LCD2s serial display unit. http://www.modtronix.com.au .

It looks physically similar to the AXE 033, but cheaper. Modtronix also have some cool pre prepared boards designed for PICs, and this is easier for me than the high cost of getting stuff from the UK. I am attempting to communicate by i2C, which should be easy for Picaxe. I replaced the $C6 in I2C address for the AXE033 with the 0x50, the address for the Modtronix unit, but i still get nothing from the Modtronix unit. It is powered but does not waver from the start up screen. In fact, when the Modronix unit is connected, instead of getting the right time on Sertxd i get question marks, which prompts me to think there is something coming back from the device.


Any ideas on how i can interface with the Modtronix LCD2S unit?



This is my code. Note much borrowed (and functional) from a previous thread by cfarr.

Code:
'clock display in i2c mode
'Serial Transmit clock time
'Write to Serial LCD.

init: 
pause 500
i2cslave 0x50, i2cslow,i2cbyte	' Modtronix display unit LCD2S

main: writei2c 0, (254,128,255)
pause 10
writei2c 0, ("THE Time is", 255)

pause 500


i2cslave %11010000, i2cslow, i2cbyte	'DS1307 Clock chip

readi2c 0,(b0,b1,b2)
pause 30


clock:i2cslave 0x50, i2cslow,i2cbyte 	' Modtronix display unit LCD2S

writei2c 0, (254,192,255)
pause 30

b4=b0 & %00001111

b3=b0 & %11110000
b3=b0/16

b3=b3+$30	' (or you could do b1=b1 + '0')
b4=b4+$30	'



b6=b1 & %00001111

b5=b1 & %11110000
b5=b1/16

b5=b5+$30	' (or you could do b1=b1 + '0')
b6=b6+$30	'



b8=b2 & %00001111

b7=b2 & %11110000
b7=b2/16

b7=b7+$30' (or you could do b1=b1 + '0')
b8=b8+$30'

writei2c 0, (b7,b8,":",b5,b6,":",b3,b4,255 )

			'Transmit to Serial Terminal

sertxd ("THE TIME IS:",b7,b8,":",b5,b6,":", b3,b4,13,10)

low 0			'flash LED on Pin 0
pause 50
high 0

goto init


Thanks,
Michael Viset
 
Last edited:

springer

New Member
I had the same type of problems writing to a non standard florescent display.
I solved it by using an 18X and playing about with the setfreq command and the serout command.

Remember that the sertxd command is a fixed baud rate at a fixed pin
The serout command can be doubled to 9600,8,n,1 by doubling the chip frequency (setfreq m8)
 

Michael V

Senior Member
Thanks Springer,
I looked it up in the manual, but can't see how to use serout. I am trying to write via I2C, and Serout is via a different type of connection. I2C is just fast and slow. I can't see what setfreq would do.

Any other ideas?

This module also allows for SPI, and in my updatad manual there is a "Shiftout" subroutine. But i'd rather conquer the I2C first.

Michael
 

hippy

Senior Member
Start with something simpler. Just trying to display "Hello World" or similar. No fancy formating, no character positioning or control codes, just the basic "can I put any character on the screen" test.
 

Michael V

Senior Member
Hi Hippy,
I tried and tried.

Double checked all the wiring. The same i2c bus is connected from the clock, and i'm programming and reading that OK.

In the data sheet they use codes like 0x80, parsed strings etc. Tried to clear the screen, write a line, turn backlight on and off - nothing.

If i go back to my original code below, i get the time in SERTXD ok, but when the additional LCD device is plugged in it gives question marks on SERTXD. It is as though it has been trying to communicate, but got lost somewhere and now it is confused.

Maybe there is some incompatability with the picaxe commands? In the LCD2S data sheet all the commands seem to be 4 digit hex, whereas in the AXE 033 they are 3 digit numeric. Is there a clue in there?

Regards,
Michael
 

womai

Senior Member
You do have pullup resistors on the two I2C lines (2.2 ... 4.7 kOhm going from clock and data line, respectively, to positive supply Vcc)?

WOlfgang
 

Michael V

Senior Member
Yes Wolfgang, the Pullups are there, much of the circuit was copied from the Picaxe datalogger circuit, with an extra I2C connection for the display. Has me baffled.

The idea is that the external display logs the most recent pressure event, pressure and time, and i can't even get it to say "Hello World" yet.

Michhael
 

100317

New Member
I have succesful tested an I2C Display 3*16 Char LPH 3827-3 with an picaxe28x.
The program I found on the internet and I modified it for my own use.

Code:
'  Anzeigedaten sind in HEX, nach Characterset A (Datenblatt PCF2116)
'  oder in Bascom-HELP ASC (ASCII Tabelle)
'  Display ist direkt an I2C-Bus angeschlossen
'  PullUp am I2C-BUS 2x 10K
'  Poti für Kontrast 100K, single supply wie Datenblatt
'  Poti an VSS und VDD, Schleifer Pin 4
'  ChipAdresse HEX 74 (write)
'  Zeilenadresse HEX (1.-3. Zeile) 80,A0,C0
'  Achtung - Je Zeile nur 12 Zeichen, Rest geht ins Nirvana
'  80 bis 8B, A0 bis AB, C0 bis CB oder 128-139,176-188,192-203
'--------------------------------------------------------------
#picaxe 28x1

#terminal 4800
	'debug
	i2cslave $74,i2cfast,i2cbyte 	‘set up i2cslave for LCD
	pause 500 ‘ wait for display to initialise
	writei2c 0,(%00000001)	'CLS

anfang:
	i2cslave %11010000, i2cslow, i2cbyte
	readi2c 0, (b0,b1,b2,b3,b4,b5,b6,b7)
	'debug

symbol wtag = b3

	

	bcdtoascii b4,b8,b9	'convert b4 in b8 und b9 --> Tag 
	bcdtoascii b5,b10,b11	'convert b5 in b10 und b11 --> Monat
	bcdtoascii b6,b12,b13	'convert b6 in b12 und B13 --> Jahr

	bcdtoascii b2,b4,b5	'convert b2 in b4 und b5 --> Stunde	
	bcdtoascii b1,b3,b2	'convert b1 in b3 und b2 --> Minute	
	bcdtoascii b0,b1,b7	'convert b0 in b1 und b7 --> sekunde
	'debug
	
schreiben:
	i2cslave $74,i2cfast,i2cbyte ‘ set up i2cslave for LCD
	pause 20 ‘ wait for display to initialise

main: 

'	writei2c 0,(%00000001)	'CLS
	writei2c 0,(%00000110)	'entry Mode
	writei2c 0,(%00001110)	'display control, cursor display , Blinken ein

	writei2c 0,($80)		'ddram adresse Hex 80
	writei2c 0,(%00101110)	'cursor display shift on
	pause 300
	
	writei2c $C0,(b8)	'Tag
	writei2c $C0,(b9)	'Tag
	writei2c $C0,(".")	
	writei2c $C0,(b10)	'Monat
	writei2c $C0,(b11)	'Monat
	writei2c $C0,(".")
	writei2c $C0,("2")	'2
	writei2c $c0,("0")	'0
	writei2c $C0,(b12)	'Jahr
	writei2c $C0,(b13)	'jahr	
	sertxd (b8,b9,".",b10,b11,".","20",b12,b13," ")
	
	writei2c 0,($A0)		'ddram adresse Hex A0
	'writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,(b4)	'Stunde
	writei2c $C0,(b5)	'Stunde
	writei2c $C0,(":")	
	writei2c $C0,(b3)	'Minute	
	writei2c $C0,(b2)	'Minute
	writei2c $C0,(":")	
	writei2c $C0,(b1)	'Sekunde
	writei2c $C0,(b7)	'Sekunde
	sertxd (b4,b5,":",b3,b2,":",b1,b7," ")
	
	wtag = 04	'#######################################################---->murks
	if wtag = $01 then sonntag
	if wtag = $02 then montag
	if wtag = $03 then dienstag
	if wtag = $04 then mittwoch
	if wtag = $05 then donnerstag
	if wtag = $06 then freitag
	if wtag = $07 then samstag
	'debug
	end
	goto wechsel
sonntag:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("S")
	writei2c $C0,("o")
	writei2c $C0,("n")
	writei2c $C0,("n")
	writei2c $C0,("t")
	writei2c $C0,("a")
	writei2c $C0,("g")
	goto wechsel
montag:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("M")
	writei2c $C0,("o")
	writei2c $C0,("n")
	writei2c $C0,("t")
	writei2c $C0,("a")
	writei2c $C0,("g")
	goto wechsel
Dienstag:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("D")
	writei2c $C0,("i")
	writei2c $C0,("e")
	writei2c $C0,("n")
	writei2c $C0,("s")
	writei2c $C0,("t")
	writei2c $C0,("a")
	writei2c $C0,("g")
	goto wechsel

mittwoch:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("M")
	writei2c $C0,("i")
	writei2c $C0,("t")
	writei2c $C0,("t")
	writei2c $C0,("w")
	writei2c $C0,("o")
	writei2c $C0,("c")
	writei2c $C0,("h")
	sertxd ("Mittwoch",CR,LF)
	goto wechsel
donnerstag:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("D")
	writei2c $C0,("o")
	writei2c $C0,("n")
	writei2c $C0,("n")
	writei2c $C0,("e")
	writei2c $C0,("r")
	writei2c $C0,("s")
	writei2c $C0,("t")
	writei2c $C0,("a")
	writei2c $C0,("g")
	goto wechsel
freitag:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("F")
	writei2c $C0,("r")
	writei2c $C0,("e")
	writei2c $C0,("i")
	writei2c $C0,("t")
	writei2c $C0,("a")
	writei2c $C0,("g")
	goto wechsel
samstag:
	writei2c 0,($C0)	'ddram adresse Hex C0
	writei2c 0,(%00101110)	'cursor display shift on
	'pause 300

	writei2c $C0,("S")
	writei2c $C0,("a")
	writei2c $C0,("m")
	writei2c $C0,("s")
	writei2c $C0,("t")
	writei2c $C0,("a")
	writei2c $C0,("g")
	goto wechsel

wechsel:
	toggle 7		'toggle LED
	goto anfang

schl:
	High 7
	pause 1000
	low 7
	pause 1000
	b1=b1 +1
	if b1 = 10 then loe
	goto schl
loe:
	writei2c 0,(%00000001)	'CLS
	goto anfang
end
Perhaps you can find some helpful information.

Hans
 

Michael V

Senior Member
Is it electrical?

Thanks Hans,
There is some useful stuff there that i can use. Good thing i can read a little german! Vielen dank!

In the process of trying the code, including the i2cfast, and retrying the code, i rechecked everything again. I am embarrassed to say that i found a short between the SDA and SCL lines of the ribbon cable between the PC board and the module. The Unit Lit up OK, with the 5V so i assumed all the connections were OK.

The question marks i got back from SERTXD instread of the time when the module was connected were obviously because of the short between SDA and SCL in the cable, and nothing to do with the module.

The ribbon cable was made up from IDC connectors and cable from Jaycar, and i just assumed it would work. So now i have to get some new bits.

Since i have work to do and am spending too much time on this i will get back in a few days.

Michael
 

hippy

Senior Member
I am embarrassed to say that i found a short between the SDA and SCL lines of the ribbon cable between the PC board and the module.
It happens to the best of us, and hardly your fault in this case. I spent an hour yesterday wondering why my LED wouldn't light with a 330R. Replaced the 33K and it worked as expected :)

Never be afraid to admit your mistakes; others are going to make them as well so better to know of them than hide them. It's far more useful to explain how something was made to work than "It's fixed Now. Thanks" with no clue as to what advice given was useful or not.

Also I'll admit that if it wasn't for having another device on the bus you'd not have realised there was a short so quickly. In some cases minimising the system doesn't necessarily move us in the right direction as fast.
 

Michael V

Senior Member
Thanks for the Encouragement

Thanks Hippy,
I too always encourage people to ask rather than not ask, and there are no dumb questions only dumb answers.

I have stolen some time to order new bits from Jaycar to arrive by overnight post. Cheaper than the petrol to drive to the shop. If Hans can get a "foreign" (no pun intended) module to work, then so can I.

Watch this space.
 

Michael V

Senior Member
Some success and Translator required

I received my bits today, made up my new cable, tested it and connected up the module. It lit up ok, and no more question marks coming from from the shorted out I2C bus. So far so good.

Following hippys advice i tried something simple - a single letter like Hans had in his code. No good. Then i started fooling around with i2cfast and slow. Nothing. Then i tried changing some of the numbers from some of the other code i had borrowed.

Imagine my surprise when a bunch of upside down silhouetted "P"s started appearing across the screen! Woo hoo!

Well now i know i'm communicating with the device, but we are clearly speaking a different language. I think i'm trying to speak Hex, but if i throw in a decimal at it then it starts to react! It's a bit like insulting someone in another language, having them abuse you, and never know what you said. Best analogy i can think of.

Here's what I mean.

The datasheet for the LCD2S at www.modtronix.com.au tells me that when the DIP switches are on the off position its address is 0x50. I know i got that part right, otherwise it would not have made special characters.

It says that all commands have to start with the start condition, then the device address byte 0x50, then the command or commands, then the stop condition. So you think it would be easy to clear the screen and go to a new line (0x0c)?

Firstly, i can't find any reference to a stop condition in all the picaxe literature on I2C. Is this relevant?

This is the code that doesn't work

Code:
'Test LCD2S Modtronix
main:
pause 500 
	i2cslave 0x50,i2cslow,i2cbyte 	‘set up i2cslave for LCD
	pause 500 		‘ wait for display to initialise

	writei2c 0,(0x50,0x0c)	'0x0c = CLS & first line
	pause 500
	
	writei2c 0,(0x80,"h")	'0x80 precedes something written
	pause 500	
	
	writei2c 0,(0x50,0x80,"h")	'0x80 precedes something written
	pause 500	

'none of these combinations givesme anything.

sertxd ("working.....",13,10)	
	
goto main
But, thhe following decimal combination gives me an upside down silhouetted P after 14 iterations of the loop, starting on the bottom line then going to the top.

Code:
'Test LCD2S Modtronix
main:
pause 500 
	i2cslave 0x50,i2cslow,i2cbyte 	‘set up i2cslave for LCD
	pause 500 		‘ wait for display to initialise

	writei2c 0,(245,128,255)	'
	' this gives me characters on the screen after 14 iterations.
sertxd ("working.....",13,10)	
	
goto main
And it happens in both i2cslow and i2cfast. Weird huh?

I guess its something to do with Hex and decimal.

Can anyone help?
 
Last edited:

BeanieBots

Moderator
I'm not too sure what the PICAXE will make of things like of "0x80" because I don't have the editor on this machine to check.
To be safe, convert the convention of "$80" to send hex values.

Got this from the link you posted which is taken from an example written in C

#define adresLCD2S_1 0x50 // DIP switch 00
#define adresLCD2S_2 0x52 // DIP switch 01
#define adresLCD2S_3 0x54 // DIP switch 10

#define backlight_on_ 0x28
#define backlight_off_ 0x20
#define clear_display_ 0x8C
#define display_on_ 0x1A
#define display_off_ 0x12
#define cursor_forward_ 0x09
#define cursor_backwards_ 0x01
#define blinking_cursor_on_ 0x18
#define blinking_cursor_off_ 0x10
#define underline_cursor_on_ 0x19
#define underline_cursor_off_ 0x11
#define move_cursor_right_ 0x83
#define move_cursor_left_ 0x84
#define shift_display_right_ 0x85
#define shift_display_left_ 0x86
#define shift_display_up_ 0x87
#define shift_display_down_ 0x88
#define write_parsed_string_ 0x80
#define line1_ 0x0d
#define line2_ 0x0a

Carry on with what you have but go even simpler. Just try to turn the backlight on and off.
Set up the I2C in the same way that you did to get "funny" characters, then send $28 pause a few seconds and send $20.
Put a pause 500 between every I2C send just to eliminate any timing issues just for now.

Good luck, hang in there! You must be close now.
 

hippy

Senior Member
It says that all commands have to start with the start condition, then the device address byte 0x50, then the command or commands, then the stop condition. So you think it would be easy to clear the screen and go to a new line (0x0c)?

Firstly, i can't find any reference to a stop condition in all the picaxe literature on I2C. Is this relevant?

This is the code that doesn't work

-- i2cslave 0x50,i2cslow,i2cbyte ‘set up i2cslave for LCD
-- writei2c 0,(0x50,0x0c) '0x0c = CLS & first line
The Start and Stop bits are an integral part of I2C and will automatically added as needed when you use I2C with the PICAXE.

The WriteI2c command is configured for use with I2C Eeproms and it looks like this is incompatible with the "0,(0x50,..)" which will send a zero byte immediately after the device address, then another 0x50 byte. One or the other, perhaps both, of these may work instead ...

-- writei2c 0x0C,(0x0C) ' Need to send at least one byte of data
-- writei2c (0x0C) ' No address sent
 

Michael V

Senior Member
Success !!!!

What a team effort. Thanks Hippy and Beanie bots, my new heroes!

Turns out you were both right. After much experimentation (while i should have been doing other things) I got this code to display on the screen:

Code:
'Test LCD2S Modtronix- This one works
main:
pause 500 
	i2cslave 0x50,i2cslow,i2cbyte 	‘set up i2cslave for LCD
	pause 500 		‘ wait for display to initialise

	writei2c  ($80,$0c)	'0x0c = CLS & first line
	pause 500
	writei2c  ($80,"Hello 1 ")	
	writei2c  ($20)		'Backlight off
	pause 500	
	writei2c  ($80,"Hello 2",$0a)'0x0a = next line
	pause 500
	writei2c  ($80,"Hello 3 ")
	pause 500	
	writei2c  ($80,"Hello 4")	

	pause 500	
	writei2c  ($28)		'Backlight on
		
	
goto main
Now i will combine it with the rest of the read clock code over the weekend.

Thanks heaps!
 

Michael V

Senior Member
Success - And even more Questions.

Hi Guys,
Well i thought i'd just pinch a bit of code from the datalogger wizard program, but that wasn't to be. After the Hex code revelation and ability to write words on the screen i struggled for some hours to get the numbers to display correctly.

After searching the picaxe forum, going over Hans's info, i did some some experimenting with the bcdtoascii command i discovered how to get the numbers i actually wanted (not crazy characters) to write on the LCD. I was also able to get the same numbers on the PC terminal screen as the LCD display.

Here s my code for Writing to the "Non Picaxe (Modtronix) display:
Code:
; *******************************
; ***** Write to LCD2s  *****
; *******************************
;    Filename: 	Write to Modtronix LCD2S 	
;    Date: 			Sept 2007
;    File Version: 	
;    Written by: 	Picaxe Wizard, Forum  & Michael V
;    Function:Get data from DS1307 clock and sisplay to LCD2s
;    Last Revision:
;    Target PICAXE:	18X & AXE-110
; ******************************* 



' ********************
' ***** Symbols  *****
' ********************

'Symbol definitions
'symbol data0 = b0
symbol data0 = b3


'symbol top_address = w2 '(b4 + b5)
'symbol address = w3     '(b6 + b7)
'symbol temp_word = w4   '(b8 + b9)
symbol secs = b0
symbol mins = b1
symbol hours = b2
symbol day = b4
symbol month = b5

symbol secs1 = b6
symbol secs2 = b7
symbol mins1 = b8
symbol mins2 = b9
symbol hours1 = b10
symbol hours2= b11
symbol data1 = b12
symbol data2 = b13


Symbol flag = 0

symbol COM = 44         'comma
symbol RET = 13         'carriage return
symbol LFEED = 10        'line feed

'Preload sensor names and title into data memory
EEPROM 0,(0,0)
EEPROM 16,("Light")
EEPROM 32,("Sensor 1")
EEPROM 48,("Sensor 2")
EEPROM 64,("Temperature")
EEPROM 80,("Event Logger with RTC")


' ***************************
' ***** Initialisation  *****
' ***************************

init:
	high 5 ' write protect eeprom
	
' Initialise Display via I2C

	i2cslave $50, i2cfast, i2cbyte	'Address of module
	writei2c  ($80,$8c)			'All word strings start with $80
							'$8c = CLS & go to first line
	pause 50
	
' *********************************
' ***** Main loop -   *****
' *********************************


main:
'Read the sensor
readadc 1, b3
'let data0 = b3 * XXXX	' Converts byte data to engineering unit (approx)

' **********************************
'Future - test for event, but for now just loop to test display
' **********************************	

Event:

' **********************************
' ***** Read event time *****
' **********************************
	
	i2cslave %11010000, i2cslow, i2cbyte
	readi2c 0,(secs,mins,hours,day)
	pause 100

' **********************************
' ***** Write to I2C display  Module and *****
' **********************************

	' Convert BCD to ASCII
	bcdtoascii hours,hours1,hours2	
	bcdtoascii mins,mins1,mins2
	bcdtoascii secs,secs1,secs2	
	bcdtoascii data0,data1,data2	
	
'Write to Modtronix LCD2S display
	i2cslave $50, i2cfast, i2cbyte	'I2CAddress of module in Hex
	pause 100	
	writei2c  ($8c)	 '$8c = CLS & go to first line
	pause 200	
	writei2c  ($80,"Time: ")		
	pause 200
	writei2c  ($80,hours1,hours2,":",mins1,mins2,":",secs1,secs2)
	writei2c  ($8a,2,1)	' Cursor Position second line first column
	pause 200
	writei2c  ($80,"Pressure-bar: ")
	pause 500	
	writei2c  ($80,data1,data2)

'Serial transmit data & time to Computer for logging with "RS232 Data Logger"
	sertxd (data1,data2,"  ",hours1,hours2,":",mins1,mins2,":",secs1,secs2,13,10)	
	
	pause 500
	
' ********************************
'Record to 24LC256 eeprom as per datalogger program	
' ********************************
'Future development
' ********************************
'Retrieve data from eeprom by polling using XBee Pro connnection	
' ********************************
'Future development	
	
	goto main
This solution gave me the desired effect. Woo hoo! But now i have another problem.

The idea of this device is as an "Event Data logger". The functionality i seek to develop is to that i can detect an event through a test loop, record the time of the event and the magnitude of the event, eg a pressure spike, Display the time and magnitude of the most recent event on the LCD, so it will remain visiable until the next similar event, and retrieve the data from the machine later.

I believe all this could be done with the AXE110 data logger off the shelf device with the attachment of the AXE LCD display, plus a bit of programming. for example, you could recod when temperatures exceeded a certain amount and for how long. But I didn't use that because i wanted the flexibility of using bigger LCDs to display more historical data to the operator than the 16 x 2 picaxe module. Other vendors have 20x 4 modules. I think i can do that now, thanks to the great advice on this forum. Secondly, access to the equipment to be monitored is difficult and not always safe, so i want to eventually retrieve the data on a daily basis by connecting via Zigbee and Picaxe connect. There is no way to connect these two devices together, so i built my own from stripboard.

In the attached photos you will see my non picaxe LCD display saying what i wanted it to, and not gobbledigook. Hooooraaaay!!!!

Also, just because this is a sharing forum, you will see a close up of the stripboard, showing 5v Power supply and serial connection (Molex) connection on the left, a LED connected to pin 0 so that i could at least get something to work, The eeprom chip under those, the 18X and the download resistors. Then under that the connector for the I2C for the LCD, mirroring those on the board, plus the 4.7 k pullup resistors, then a five pin terminal header for future connection to an external Xbee board i still have to build, (same pin connections as XBEE connect, so i can steal more code) then the battery for the RTC, the RTC and the crystal, the LED that goes at 1HZ and drives you nuts, and above that a connector that allows me to connect to two inputs to ADC and 5 v. All the bridges are on the top of the board, only holes in the stripboard on the bottom,. i.e no wires underneath.

So, having said all that, my problem is that using BCDTOASCII i have used up just about all of my byte variables. There is not enough variables for me to record or display the day and month, and i have also used up the ones that were previously allocated to to writing and reading from the EEPROM, and i'd like them back so i can use tyhe tried and proven code.

Any ideas how to make the variables go further?

Michael Viset
 

Attachments

BeanieBots

Moderator
There are a number of tricks you can use.
If you just want one extra variable, you can use infra just like you can b0.
To save a few variables, look at using a temporary store. That is, before you use the variable for a second function, save it to a variable you have assigned as temporary store, then get the original value back after you have finished. eg
b0=ValueToKeep
b1=b0
b0=SomeOtherValue
..do something with it
b0=b1 gets the original value back

There is also peek and poke which can be used to store variables in user RAM.
 

Michael V

Senior Member
Still Struggling with Variables

Thanks BB,
I searched and hunted through the threads, and went over peek and poke (or poke and peek as it turns out) but am struggling to see how it works from a practical point of view.

Also storage variables - I think i'm already doing it, but it just looks messy and inelegant, a lot of lines of code.

Here's what i mean:

This code reads the value from a 0-5V pressure transducer, displays it via I2C on a non-AXE LCD display with the current time read from the DS1307. I read in another thread that someone wanted to output percent, and i thought that was a good idea so i added that as well. In order to do all this i made use of three recycled temporary variables and the bintoascii and bcdtoascii commands.

The code also writes the data via the sertxd command back to the computer. You may think why bother, but i discovered a neat program called RS232 data logger on the net at http://www.eltima.com/products/rs232-data-logger/. Using this free program you don't have to have the program editor running, and you can use any old second hand computer from Win 98 upwards to log your data to a .txt file. If you put approriate delimiters in your sertxd command then you can manipulate the txt file with Microsoft Excel. Perfect for Event Data logging. Would also work with Picaxe o8m, and you save on all the grief of manipulating a Serial LCD, which is what started me on this thread in the first place.


Anyway, heres the code that i think has too many lines and is therefore inefficient:

Code:
'PICAXE-18X - Read RTC then output via 
'SERTXD serial output to computer, and  
'I2C to Modtronix LCD2S Serial Display unit
'Mostly generated by Picaxe Datalogger  Wizard
'Subsequently modified by Picaxe Forum and Michael V

'V4

' ********************
' ***** Symbols  *****
' ********************

'Symbol definitions
'symbol data0 = b0
symbol data1 = b3

'symbol top_address = w2 '(b4 + b5)
'symbol address = w3     '(b6 + b7)
symbol temp_word = w4   '(b8 + b9)
symbol temp_byte1 = b10
symbol temp_byte2 = b11
symbol temp_byte3 = b8
symbol secs = b0
symbol mins = b1
symbol hours = b2
symbol day = b4
symbol month = b5

symbol COM = 44         'comma
symbol RET = 13         'carriage return
symbol LFEED = 10        'line feed

'Preload sensor names and title into data memory
EEPROM 0,(0,0)
EEPROM 16,("Light")
EEPROM 32,("Sensor 1")
EEPROM 48,("Sensor 2")
EEPROM 64,("Temperature")
EEPROM 80,("Event Logger with RTC")


' ***************************
' ***** Initialisation  *****
' ***************************

init:
	high 5 ' write protect eeprom
	
' Write to Modtronix Display via I2C

	i2cslave $50, i2cfast, i2cbyte	'Address of module
	writei2c  ($80,$8c)			'$8c = CLS & go to first line
	pause 100
	
	sertxd ("Reading , ","Year, ","Month, ","Day","Time, ",13,10)	
' *********************************
' ***** Main loop -   *****
' *********************************

'Read each sensor
main:
	readadc 1,data1	'Read pressure sensor
	pause 30
	
	'Read time now
	i2cslave %11010000, i2cslow, i2cbyte
	readi2c 0,(secs,mins,hours,temp_byte1,day,month,temp_byte3)
	pause 100
	
'Write to PC via Sertxd
	sertxd (#data1,", ")
	pause 1000
	bcdtoascii temp_byte3,temp_byte1,temp_byte2	'writes year
	sertxd (temp_byte1,temp_byte2,", ")	
	bcdtoascii month,temp_byte1,temp_byte2	'writes month
	sertxd (temp_byte1,temp_byte2,", ")
	
	bcdtoascii day,temp_byte1,temp_byte2	'writes day
	sertxd (temp_byte1,temp_byte2,", ")
	
	bcdtoascii hours,temp_byte1,temp_byte2
	sertxd (temp_byte1,temp_byte2,":")	

	bcdtoascii mins,temp_byte1,temp_byte2
	sertxd (temp_byte1,temp_byte2,":")
	
	bcdtoascii secs,temp_byte1,temp_byte2
	sertxd (temp_byte1,temp_byte2,13,10)

' **********************************
' ***** Write to I2C display  Module and *****
' **********************************

'Write to Modtronix LCD2S display
	i2cslave $50, i2cfast, i2cbyte	'I2CAddress of module in Hex
	pause 500	
	writei2c  ($8c)	 '$8c = CLS & go to first line
	pause 500	
	writei2c  ($80,"Time: ")		
	pause 200
	bcdtoascii hours,temp_byte1,temp_byte2	
	writei2c  ($80,temp_byte1,temp_byte2)
	writei2c  ($80,":")	
	bcdtoascii mins,temp_byte1,temp_byte2
	writei2c  ($80,temp_byte1,temp_byte2)
	writei2c  ($80,":")	
	bcdtoascii secs,temp_byte1,temp_byte2
	writei2c  ($80,temp_byte1,temp_byte2)

	pause 200	
	writei2c  ($8a,2,1)	' Cursor Position second line first column
	
	writei2c  ($80,"Pressure ")
	pause 200
'	writei2c ($80,data1)
	if data1 = 255 then ninety_nine 'ensures maximum not 100%
	let data1 = data1*100/255	'converts analog data to percent, max 99
	bintoascii data1,temp_byte1,temp_byte2,temp_byte3
	
	writei2c  ($80,temp_byte2,temp_byte3," %")		
	
	pause 500
		
	goto main


ninety_nine:
let data1 = 254
return
If you think it can be improved, especially shortened or made quicker (lots of pauses in there), please let me know.

Regarding the poke and peek and temporary storage variables, are there some practical examples you you can refer me to? I'm not having much luck searching the Forum.

I'm going to need them as my project develops to actual data logging and data retrieval by Xbee. This is turning out to be a bigger challenge than i thought.

But for now, i have achieved the original objective of "Write to non Picaxe LCD Display" (signal to moderator to close thread, don't know how that is done). I'm about to go off on a four week trip, and will be sure to be asking questions on a new thread about the Event Data Logger when i get back.

Updated photo of display attached.

Regards,
MV
 

Attachments

BeanieBots

Moderator
We don't normally close threads but with the new layout, you never know!

Optimising code:-
Personally, I don't bother unless there is a gain to be had such as running too slow or can't fit the last few lines into the chip. Always a good idea to get into the habit of writting efficiently in the first place but squeezing the last bit out can be very time consuming and not worth it if not actually required. Others may have a different opinion but for me, my time is the most valueable commodity and not PICAXE program space. Like most things, it's a balancing act.

As for peek and poke. Possibly one of the most effective uses is like a "stack" when using sub routines. Let's say you have used most of your variables in the main program and want to do some data manipulation in a subroutine.

The first line of the subroutine 'pokes' each value of each variable you need to use into RAM.
Those variables are now free to use in the routine.
At the end of the routine, 'peek' them back and return.
The main program is totally unaware that its variables have been used for another purpose. Obviously, the subroutine itself may well use data that has been previoulsy 'poked' either by another routine or by itself earlier on.

Another use that I personally have implement several times, is when you have a lot of data that needs to be displayed but not always at the same time. For example, my fish-tank controller only has a 2 X 16 display but from menu buttons I can select Temp,Time,Power,Lights on time, lights off time, integral term, derivative term, prop term and a few others. These are all calculated at one second intervals and the results are stored in RAM because there are not enough variables to hold them all. When the appropriate menu is selected, the display routine is simply made to 'point' to the right RAM location. Also means I only need one display routine that does little else than put 16 characters from RAM onto the display.
 

Michael V

Senior Member
The clock is eating my variables

Thanks BB,
I think i get the idea - but will need to experiment with poking and peeking (later, have real work to do)

But even with the Poke and peek one thing that is still a problem is reading the clock. I am building an event data logger, and want to record the time of the events. In my initial application i want to record pressure spikes which occur about 2-3 times per minute over a month between machine services. But then i (or others) may want to measure events less frequently, eg daily max and min temperatures.

This means that I have to from the clock record seconds, min, hour,day, and also need to temporarily retrieve the week day to get month and year. That is even if i only want to record the date for daily temp max/mins then i still have to use eight variables, even though five of them will be temporary.

Is there any way around this?

If there is i can put the less frequently changing data in the poke, which will free up variables (i think).

Regards,
MV
 

BeanieBots

Moderator
So you've used 8 variables. You've got 6 (7) left to play with.
The subroutine that reads the clock, pokes them into RAM for safe keeping and you've got all 14 (15) ready to use for something else.
I think you've got it. You just don't know it yet!
 

Michael V

Senior Member
Peace wth Poke and Peek

You were right!

My mental obstacle was in the "Symbols" section of the code, where different aliases were assigned different numbers from b0 to whatever. As it turns out you can Symbol XXX = b0 as many times as you like. All it does is defines a particular bunch of letters as a byte variable (or word variable) the actual value of b? is meaningless. But i guess you knew that.

So i added a bunch of POKESs after i read the time. This makes all my variables available to be temporary, until i want to display and record the time.

I added an extra piece of simple code which would write the date over the top on the time, extracting the variable data using PEEK.

It works. And, when i have more time i will make it look easier to read.
Code:
'PICAXE-18X - Read RTC then output via 
'SERTXD serial output to computer, and  
'I2C to Modtronix LCD2S Serial Display unit
'Mostly generated by Picaxe Datalogger  Wizard
'Subsequently modified by Picaxe Forum and Michael V
'V4
'This one uses Poke and Peek


' ********************
' ***** Symbols  *****
' ********************

'Symbol definitions
symbol data0 = b0
symbol data1 = b3

symbol top_address = w2 '(b4 + b5)
symbol address = w3     '(b6 + b7)
symbol temp_word = w4   '(b8 + b9)
symbol temp_byte1 = b10
symbol temp_byte2 = b11
symbol temp_byte3 = b8
symbol secs = b0
symbol mins = b1
symbol hours = b2
symbol day = b4
symbol month = b0
symbol year = b0

symbol COM = 44         'comma
symbol RET = 13         'carriage return
symbol LFEED = 10        'line feed

'Preload sensor names and title into data memory
EEPROM 0,(0,0)
EEPROM 16,("Light")
EEPROM 32,("Sensor 1")
EEPROM 48,("Sensor 2")
EEPROM 64,("Temperature")
EEPROM 80,("Event Logger with RTC")


' ***************************
' ***** Initialisation  *****
' ***************************

init:
	high 5 ' write protect eeprom
	
' Write to Modtronix Display via I2C

	i2cslave $50, i2cfast, i2cbyte	'Address of module
	writei2c  ($80,$8c)			'$8c = CLS & go to first line
	pause 100
	sertxd ("Reading , ","Year, ","Month, ","Day","Time, ",13,10)	
' *********************************
' ***** Main loop -   *****
' *********************************

'Read each sensor
main:
	readadc 1,data1	'Read pressure sensor
	readadc 0,data0	'Read pressure sensor	
	pause 30
	
	'Read time now
	i2cslave %11010000, i2cslow, i2cbyte
	readi2c 0,(secs,mins,hours,temp_byte1,day,month,year)
	pause 100
	poke 80, secs
	poke 81, mins
	poke 82, hours
	poke 83,temp_byte1
	poke 84,day	
	poke 85,month
	poke 86,year	
		
'do other things with the variables
'Write to PC via Sertxd
	sertxd (#data1,", ")
	pause 1000
	bcdtoascii year,temp_byte1,temp_byte2	'writes year
	sertxd (temp_byte1,temp_byte2,", ")	
	bcdtoascii month,temp_byte1,temp_byte2	'writes month
	sertxd (temp_byte1,temp_byte2,", ")
	
	bcdtoascii day,temp_byte1,temp_byte2	'writes day
	sertxd (temp_byte1,temp_byte2,", ")
	
	bcdtoascii hours,temp_byte1,temp_byte2
	sertxd (temp_byte1,temp_byte2,":")	

	bcdtoascii mins,temp_byte1,temp_byte2
	sertxd (temp_byte1,temp_byte2,":")
	
	bcdtoascii secs,temp_byte1,temp_byte2
	sertxd (temp_byte1,temp_byte2,13,10)

' **********************************
' ***** Write to I2C display  Module and *****
' **********************************

'Write to Modtronix LCD2S display
' Get time data
	peek 80, secs
	peek 81, mins
	peek 82, hours
	peek 83,temp_byte1



	i2cslave $50, i2cfast, i2cbyte	'I2CAddress of module in Hex
	pause 500	
	writei2c  ($8c)	 '$8c = CLS & go to first line
	pause 500	
	writei2c  ($80,"Time: ")		
	pause 200
	bcdtoascii hours,temp_byte1,temp_byte2	
	writei2c  ($80,temp_byte1,temp_byte2)
	writei2c  ($80,":")	
	bcdtoascii mins,temp_byte1,temp_byte2
	writei2c  ($80,temp_byte1,temp_byte2)
	writei2c  ($80,":")	
	bcdtoascii secs,temp_byte1,temp_byte2
	writei2c  ($80,temp_byte1,temp_byte2)
	pause 1000
	

' Get date data
	peek 84,day	
	peek 85,month
	peek 86,year
'write the date over the top of the time
	writei2c  ($8c)	 '$8c = CLS & go to first line
	pause 500	
	writei2c  ($80,"Date: ")		
	pause 200
	bcdtoascii day,temp_byte1,temp_byte2	
	writei2c  ($80,temp_byte1,temp_byte2)
	writei2c  ($80,":")	
	bcdtoascii month,temp_byte2,temp_byte3
	writei2c  ($80,temp_byte2,temp_byte3)
	writei2c  ($80,":")	
	bcdtoascii year,temp_byte1,temp_byte2
	writei2c  ($80,temp_byte1,temp_byte2)
	pause 1000


' Cursor Position second line first column
	writei2c  ($8a,2,1)
	
	writei2c  ($80,"Pressure ")
	pause 200
	if data1 = 255 then ninety_nine 'ensures maximum not 100%
	let data1 = data1*100/255	'converts analog data to percent, max 99
	bintoascii data1,temp_byte1,temp_byte2,temp_byte3
	
	writei2c  ($80,temp_byte2,temp_byte3," %")		
	
	pause 500
		
	goto main


ninety_nine:
let data1 = 254
return
Thanks. This opens up the possibilities. What a wonderful little chip.

Michael Viset
 

BeanieBots

Moderator
You've got it.
I'm a bit sloppy when it comes to the use of 'symbol'.
I tend to use it more for defining the location where my data is.
Example taken from PID heater controller.

symbol Ave_ptr = $C0 'Counter used by averaging subroutine.
symbol PWR_dem1 = $C1 'Percentage Power Demand.
symbol PWR_dem2 = $D3 'power demand for heater 2
symbol PWR_ctr1 = $C8 'Ramp position counter used by Slow PWM.
symbol PWR_ctr2 = $D4 'same but for heater 2
symbol Temp0 = $E0
symbol Temp1 = $E1 etc. etc

subroutine_NNN
poke temp0,b0 'save current values of b0 & b1
poke temp1,b1
peek Ave_ptr,b0 'get values that this routine needs
peek PWR_dem1,b1
..do something with b0 & b1
poke Ave_ptr,b0 'save new value
poke PWR_dem1,b1
peek temp0,b0 'get original values back
peek temp1,b1
Return 'with b0 and b1 unaffected by this routine.
 

Michael V

Senior Member
More to Get My head around!

Thanks BB,
I was just following the manual. But i can see your point (I think).

Instead of poking direct to a location, you use Symbol to define the location and the more easily understandable alias name you have given it, then you peek and poke some temporary variable to the name, which automatically puts it into the Poke registry. Is that it?


But i'm confused about the $ signs, which i should have less trouble than for you guys, since i don't have "pound" signs on my keyboard. Why the $ sign and not a decimal, like it says in the manual? I know its somethhing to do with hex, form my experience of writing to the display (woo hoo) but can't see the relevance of hex here.


More to get my hear around, and i have some real work to do....
 

BeanieBots

Moderator
By all means use whatever number system you feel happy with.
I prefer to work in hex because (believe it or not) I find it easier!
Micros tend to be organised in blocks of 8 or 16. The LCD display just happens to have 2 X 16 lines. The RTC stores its data as BCD which can be viewed as hex to show two digits at a time. If you want to get say the 10's of seconds, and'ing with $F0 or %11110000 is so much more obvious than anding with 240.
Let's say you wanted to store some text to display.
You try to remember (or keep a note of) where those messages are.
In hex, just add one to the second digit and you are at the next message.

Before long, you will find that decimal is actually not a particularly useful number system. Ever wondered why there are 60 seconds to a minute rather than 100, or 360 degrees in a circle. It's actually to make the maths easier!
Even the old UK money system, 12 pence to the shilling and 240 to the pound had a lot of merits before calculators and sums had to be done in the head.
 

Michael V

Senior Member
The time got stuck???

Thanks BB,
But Picaxe is still a hobby, and i don't plan on being a hexpert just yet. But i do understand that there are 10 types of people, those that understand binary and those that don't.

Now, my litttle clock has been going along happily, but this morning i noticed that the time was stuck. The time was the same as the date, and there was a 37th of the month.

I can only think that when i moved it last night and shorted the supply line for a couple of seconds (note dodgy wiring in previous photos, and no incoming capacitor i have just noticed) that something happened to the clock.

I reloaded the last code with Poke and peek, the time was still stuck. Then i loaded the previous one without the poking, still stuck. Then i used the trusty Picaxe Wizard datalogger time set program, then my most recent code with the poking, and now its back to normal again.
I can only conclude that shorting out the supply line froze the clock somehow, but that's what i thought the lithium battery was supposed to protect against. I have checked it and the DS1307 chip is getting the right volts from the battery.

Anyone have any ideas as to what happened?
 

BeanieBots

Moderator
You don't need to be a "hexpert" to reap the benefits of hex. It really is a clearer way of representing many numbers in a computing environment.

The RTC is very prone to noise. I expect it locked up because shorting the supply doesn't just drop the volts, it creates all manner of spikes both high low and even negative. A 100nF cap on both the PICAXE and the RTC would probably have prevented lockup but even with them, sparks are likely to upset it. The battery backup works well and lasts for years on a lithium cell.
 

Michael V

Senior Member
100 nf Capacitor Location

Thanks BB,
When i progress i'll make the design more robust to avoid shorts, i can see that there would be spikes and that explains it. And i'll add the capacitors.

The PicaXe Datalogger circuit does not have a 100nf capacitor on the RTC. When you say "A 100nF cap on both the PICAXE and the RTC would probably have prevented lockup" does that mean across the + and ground as physically close to the chip as possible?
 

BeanieBots

Moderator
Yes, 100nF as close as possible to the power pins. They are called "decoupling" capacitors. They work both ways. They stop noise getting into the chip via the power rail, and they prevent current spikes caused by the chip getting onto the power rail.
 

BrendanP

Senior Member
BB, why is it important to have the caps close as possible to the pins on the IC? Is it because the tracks on the pcb have a minute amount of capacitance themselves?
 

BeanieBots

Moderator
Many reasons.
The tracks act as aerials and will transmit noise.
The tracks have resistance that will cause volt-drop noise.
The tracks have inductance that can cause resonance.
The track between chip and cap will be noisy and shouldn't have anything else connected to it (because of the noise).
The caps ability to suppress is effected by the total impedance (cap+track)

Back in reality you can often get away without any but as soon as spurious resets start to happen or counters click over without being clocked then decoupling caps often fix the problem.
The longer the tracks, the poorer the layout and the worse the solder joints, the more important decoupling caps become.
 

andrew_qld

Senior Member
Modtronix i2c LCD Code

I have one of the Modtronix i2c LCD's and I have some simple picaxe code on my LCD page which should help you get started with it. It's all pretty well documented and explained in the basic file. My LCD page is at http://www.andrew.meachen.net/LCDs.html and I have tried to attach the basic code I used as well as the URL but as this is my first post forgive me if it doesn't work!

Cheers,
Andrew
 

Attachments

Michael V

Senior Member
Lively LCDs

Hi Andrew,
Youve done some work on LCD Displays.

Further down the track i will want to go from picaxe to the 20 x 4 display via I2C, and will use the Modtronix display with bar graphs and Big letters. Your web site and code will help with that. Something a little different that i ended up with. There is no AXE 20 x 4, it seems.

Also the Modtronis 28sbc is ALMOST Picaxe 28X1 compatible. I have worked out that the PIC in circuit programming points do not line up with the Picaxe ones. But all the resistors and connectors for the Picaxe programming connector ( plus maybe an extra decoupling capaitor or two - i'm learning) can go on the prototype daughter board which is only cheap. I haven't done it yet, just spent too much time liooking at it. If it works ok the dedicated micro match connector will directly connect I2C or SPI - to Displays or anything else.

And the two orders i got from Modtronix arrived the next day - advantage of being in the big city.

For our UK buddies, apparently you can get Modtronix bits from skpang.co.uk, there is also a german site, but the prices mean nothing to me in comparison.

Now, back to work.
 

andrew_qld

Senior Member
Michael,
The SBC28 should work OK with the Picaxe 28x1 without even using the daughter board, you would just have to figure out a way to connect the standard programming lead to the board. I would just run a wire from the RA4 & RA5 connectors and a ground to a 3.5mm socket. I'd probably cut the track to the PIC RA4 connector using a knife or a dremmel and solder a 22k resistor accross it on the board, then solder a 10k resistor from it to any handy ground point on the board- not to difficult at all.

Cheers,
Andrew
 
Top