Picaxe 40x2 and Axe033 LCD problem

pyrogaz

Member
I'm building a combined speed controller, driver display and datalogger for an electric car using a 40x2 picaxe chip as the processor. The 40x2 provides a PWM output to the speed controller and adjusts it so that a predefined current set on a rotary pot is maintained. It also sends raw data from various sensors to an Openlog microSD datalogger. All of the above it seems to be doing very well, the problems arise when I try to display information on the AXE033 LCD for the driver.

There are two lines of data I wish to display, one is the individual voltage of two batteries and current draw; the other is motor temperature and PWM duty percentage. I can display the voltages and current on either or both lines without fault, but as soon as I try to display temp and PWM duty on either line all I get is odd characters and erratic behaviour that also interfere with the other line of the display. I've tried using word variables with no success, various values of pulldown resistors on the output pin, both picaxe and LCD are powered by the same regulated 5v supply so I'm now at a loss.

I'd be grateful if someone could have a look at the code, maybe I've done something stupid somewhere! At the moment I've got the voltage and current line displaying on the top with my other options commented out and this works, but as soon as I make the code active that sends variables 28 and 30 to the bottom line it just makes a mess.

Code:
'THSYE Picaxe based speed controller, G C-S 13/02/10
'40x2 processor, current limit set by pot, button to initiate.
'Serial output to LCD, serial output to Openlog datalogger

setfreq em16		'processor speed
settimer t1s_16		'sets increments for timestamp to be recorded to datalogger
serout B.7,N2400_16,(254,1) 'clear LCD display
pause 10000			'Allows time for Openlog datalogger to initiate
w9=0				'variable for pwm duty set to zero at startup
b27=0				'logging loop counter set to zero
input d.0			'pin for "go" button set as input
goto startup


startup:
b27=b27+1			'periodical logging loop
if b27=200 then
goto serial1
else endif
if b26>70 then		'check motor temp is OK
goto limphome		'if motor hot goes to low power setting
else endif
if pind.0=1 then		'check if "go" button is pressed
goto minpow			'if not pressed go to power off routine
else
goto currcontrol		'if pressed will go to control loop
endif

limphome:			'allows car to return to pits at low power setting
if pind.0=1 then		'check if "go" button is pressed
goto minpow
else
w9=200			'set to low power 
pwmout C.1 , 249, w9
endif

currcontrol:

readadc10 0,w0		'toroidal current sensor
readadc10 1,w1		'current limiting rotary pot

w4=w1/13+580			'scale pot reading to match current sensor range

if w0>w4 then powdown		'decide which way to adjust motor power to reach target current
if w0<w4 then powup

powdown:

if w9<25 then minpow	'prevents w9 overflowing back
w9=w9-3			'increments w9 downwards to match target current
pwmout C.1 , 249, w9	'sets pwm duty
goto startup

powup:

if w9>975 then maxpow	'prevents w9 overflowing above 1000
w9=w9+3			'increments w9 upwards to match target current
pwmout C.1 , 249, w9	'sets pwm duty

goto startup


maxpow:
w9=1000			'puts pwm to maximum setting
pwmout C.1 , 249, w9
goto startup

minpow:

w9=0				'puts pwm to minimum setting
pwmout C.1 , 249, w9
goto startup

serial1:
readadc10 0,w0		'toroidal current sensor, re-reads this sensor 
readadc10 2,w2		'Battery A potential divider
readadc10 3,w3		'Battery B potential divider
readadc10 5,w5		'Motor temperature thermistor
'readadc10 6,w6		'CVT slider pot


b20=w0-507*10/51		'calc current digits
b21=w0-507*10//51*10/51	'calc current decimal

b22=w2/76			'calc Bat A voltage digits
b23=w2//76*10/76		'calc Bat A voltage decimal

b24=w3/76			'calc Bat B voltage digits
b25=w3//76*10/76		'calc Bat B voltage decimal

b30=w5-280/8		'calc motor temp
b28=w9/10			'calc % pwm setting

   
'temp and power settings for top line of lcd

'pause 50
'Serout B.7,N2400_16,(254,128,#b30,"  ")
'pause 50
'Serout B.7,N2400_16,(254,134,#b28,"  ")
'pause 50

'battery voltages and current for top line of lcd

pause 50
serout B.7,N2400_16,(254,128,#b22,".",#b23," ")
pause 50
serout B.7,N2400_16,(254,134,#b20,".",#b21,"   ")
pause 50
serout B.7,N2400_16,(254,140,#b24,".",#b25," ")


'temp and power settings for bottom line of lcd

'pause 50
'Serout B.7,N2400_16,(254,192,#b30,"  ")
'pause 50
'serout B.7,N2400_16,(254,198,#b28,"  ")


'battery voltages and current for bottom line of lcd



'pause 50
'serout B.7,N2400_16,(254,192,#b22,".",#b23," ")
'pause 50
'serout B.7,N2400_16,(254,198,#B20,".",#B21,"   ")
'pause 50
'serout B.7,N2400_16,(254,204,#b24,".",#b25," ")


high d.4		'set pin high prior to sending raw data to openlog
pause 10
serout d.4,t9600_16,(#w0,",",#w1,",",#w2,",",#w3,",",#w4,",",#w5,",",#w6,",",#w9,",",#timer,cr)
b27=0
goto startup
 

westaust55

Moderator
What values are you receiving for the READADC 3, w5 for the motor temp thermistor.

IF W5 is >2328, then your calculation for b30 (ie b30 = w5 -280 / 8) will result in overflow and you will have strange results displays - the values may (?) become control values affecting the AXE033 display

The same applies for b28. If w9 is greater than 2550, then w9 / 10 will result in overflow for variable b28.

Maybe try printing out w9 and w5 directly to see what values are being recorded before then maths are undertaken.
 
Last edited:

pyrogaz

Member
Thanks for your reply,

w9 ranges from 0-1000 and w5 is around 490 at ambient temperature, so I don't think it can be an overflow problem.

I should add that this problem occurs on the bench without it even being connected to a potentially "noisey" electric motor.
 

hippy

Ex-Staff (retired)
I cannot see anything wrong with the code itself. Cut down to just SEROUT's and PAUSE's, it runs okay with an AXE033 on a 40X2 I tested with "SETFREQ M8" and 20X2 with "SETFREQ M16". Though not tested with "EM16" I cannot see any reason it would not work if the previous line is displayed okay. It's not a "SETTIMER" issue as as I left that in.

The only thing I can suggest is try running at a slower speed and/or increasing the PAUSE times, see if that has any affect on things.
 

Technical

Technical Support
Staff member
Try slowing down to 8 (or even 4) for the actual serout lines e.g.

setfreq m8
serout B.7,N2400_8,(254,128,#b30," ")
setfreq em16

The reason behind this thinking is the AXE033 needs a short amount of processing time between each serial byte received to actually process and display the character. If you were right on the threshold point of this processing time some would be processed in time and some would not, leading to corrupt digits. By slowing the clock down of the sending PICAXE you give the AXE033 a marginally extra amount of extra time to do the 'between each byte' processing (the AXE033 IC is fairly old and only runs at 4MHz).

Another option is to use

bintoascii b30,b1,b2,b3
serout B.7,N2400_8,(254,128,b1,b2,b3)

instead of #

Again this is marginally slower to transmit, giving the AXE033 time to process.
 
Last edited:

pyrogaz

Member
Thanks for the suggestions

bintoascii has worked although I'm still a little perplexed as to why.

I tried slowing it down and longer pauses but no improvement, also tried reducing the pauses to 10 at 16mhz and still worked as it was before so speed/pauses didn't seem to be the issue. However as long as I have a working solution I'm happy!
 

hippy

Ex-Staff (retired)
For a SEROUT which sends individual bytes, such as digits produced by BINTOASCII, the process is to read the variable, send it, read the next variable, send that, and repeat until all bytes sent. There is a gap between sending each digit while the firmware gets the next to send. During this time the AXE033 processes what it's just received, updates the LCD and so on ...

Code:
SerOut ... ( b0, b1, b2 )

   Read     Read   Send   Read   Send   Read   Send
  Command    b0     b0     b1     b1     b2     b2

|<------->|<---->|<---->|<---->|<---->|<---->|<---->|
|         |      |      |      |      |      |      |
                        |<---->|
                           GAP
When the # is used in the command, the value of the variable is retrieved, individual digits are determined and these are output one after another. Not to scale, but this process is faster than the above so there is less time between bytes being sent, which means the AXE033 has less time to update the LCD and so on and it may not be ready for the next byte sent. This gets worse with higher speeds as the gaps in both cases become less ...

Code:
SerOut ... ( #b3 )

   Read     Read   Decode   Send     Send     Send
  Command    b3      b3     100s      10s      1s

|<------->|<---->|<------>|<---->|-|<---->|-|<---->|
|         |      |        |      | |      | |      |
                                 GAP
 

BeanieBots

Moderator
Can't say that I've ever had that issue with an AXE033 even at higher clock speeds but I have had garbled characters due to clock speed discrepancies.
Might be worthing trying the original problematic code with a 'calibfreq' to pull it one way or another even if just for your own sanity to resolve the root cause.
 

hippy

Ex-Staff (retired)
You can't use CALIBFREQ with an external resonator :)

The logic of Technical's reasoning and suggested use of BINTOASCII is sound, and any baud rate error would be expected to affect data sent no matter what the spacing between bytes used. With external resonator the baud rate should be consistent every time.

Suggesting CALIBFREQ may explain some things though; using internal oscillator it may be that, while there may be baud rate drift, any discrepancy pushes the '#var' use to the side of not being a problem, or adjusting CALIBFREQ achieves that. Using a resonator puts it more on the borderline.
 

BeanieBots

Moderator
To be honest I'd missed the "em16" in the original post:eek:
My thinking was that if on the edge, garbled characters could appear almost anywhwere within the 'string' and possibly only effect certain one's depending on their binary pattern. Just another thing to try out, more for curiousity.
 

pyrogaz

Member
OK, just discovered that I need to use bintoascii for any variable that might extend to more than one character, so looks like it's going to get very heavy on byte variables, although I think there should be enough.
 

hippy

Ex-Staff (retired)
or you can just turn the speed down, in total or when you come to update the LCD, as suggested by Technical in post #5.

If you choose the BINTOASCII route you can also re-use variables which hold digits, split each number to be output one at a time into digits, output those, on to the next.
 

pyrogaz

Member
Turning the speed down didn't make any difference.

Good point about reusing variables, although as there are a few students who will have to understand the system it might be better if I can keep each varaible for a specific use to simplify matters.
 
Top