PDA

View Full Version : serial coms - again



malc-c
- 20th August 2010, 17:28
Can someone point me in the right direction. An acquaintance is working with me on my thermostat project (he is writing the PC application) and I've stumbled upon a problem that I can't seem to resolve.

The following code outputs data via the port to the application


Hserout [dec Temperatures[0],dec Temperatures[1],dec Temperatures[2],dec Temperatures[3]]
HSEROUT [dec normtemp[0],dec normtemp[1],dec normtemp[2],dec normtemp[3]]
HSEROUT [dec alarmlow[0],dec alarmlow[1],dec alarmlow[2],dec alarmlow[3]]
HSEROUT [dec alarmhigh[0],dec alarmhigh[1],dec alarmhigh[2],dec alarmhigh[3]]
HSEROUT [dec lightoffHR[0],dec lightoffMN[0],dec lightoffHR[1],dec lightoffMN[1]]
HSEROUT [dec lightsetHR[0],dec lightsetMN[0],dec lightsetHR[1],dec lightsetMN[1]]
HSEROUT [dec Droptemp[0],dec Droptemp[1],dec Droptemp[2],dec Droptemp[3]]
HSEROUT [dec StopHour[0],dec StopMin[0],dec StopHour[1],dec StopMin[1],dec StopHour[2],dec StopMin[2],dec StopHour[3],dec StopMin[3]]


It compiles and the PIC runs as it should and data is sent to the PC, and displayed withing the interface.

However as soon as I enter a HSERIN line as



Hserin [dec Temperatures[0],dec Temperatures[1],dec Temperatures[2],dec Temperatures[3]]
HSERin [dec normtemp[0],dec normtemp[1],dec normtemp[2],dec normtemp[3]]
HSERin [dec alarmlow[0],dec alarmlow[1],dec alarmlow[2],dec alarmlow[3]]
HSERin [dec alarmhigh[0],dec alarmhigh[1],dec alarmhigh[2],dec alarmhigh[3]]
HSERin [dec lightoffHR[0],dec lightoffMN[0],dec lightoffHR[1],dec lightoffMN[1]]
HSERin [dec lightsetHR[0],dec lightsetMN[0],dec lightsetHR[1],dec lightsetMN[1]]
HSERin [dec Droptemp[0],dec Droptemp[1],dec Droptemp[2],dec Droptemp[3]]
HSERin [dec StopHour[0],dec StopMin[0],dec StopHour[1],dec StopMin[1],dec StopHour[2],dec StopMin[2],dec StopHour[3],dec StopMin[3]]

Hserout [dec Temperatures[0],dec Temperatures[1],dec Temperatures[2],dec Temperatures[3]]
HSEROUT [dec normtemp[0],dec normtemp[1],dec normtemp[2],dec normtemp[3]]
HSEROUT [dec alarmlow[0],dec alarmlow[1],dec alarmlow[2],dec alarmlow[3]]
HSEROUT [dec alarmhigh[0],dec alarmhigh[1],dec alarmhigh[2],dec alarmhigh[3]]
HSEROUT [dec lightoffHR[0],dec lightoffMN[0],dec lightoffHR[1],dec lightoffMN[1]]
HSEROUT [dec lightsetHR[0],dec lightsetMN[0],dec lightsetHR[1],dec lightsetMN[1]]
HSEROUT [dec Droptemp[0],dec Droptemp[1],dec Droptemp[2],dec Droptemp[3]]
HSEROUT [dec StopHour[0],dec StopMin[0],dec StopHour[1],dec StopMin[1],dec StopHour[2],dec StopMin[2],dec StopHour[3],dec StopMin[3]]


The compiled code causes the PIC to hang. - Remove the HSERIN section and it runs ! (this is regardless if the serial cable is connected to the PC or not, or if the application is runnig or not )

Bruce
- 20th August 2010, 17:38
Try it without the DEC modifiers on your HSERIN lines.

And it's going to hang until all bytes it's expecting arrive unless you use a timeout/label option.

malc-c
- 20th August 2010, 18:10
Bruce, thanks for the prompt reply.

I've tried commenting out all but the first vairiable so it is only expecting only one value, but that still caused the thing to run really really slowly :( ... as does removing the DEC modifier :( could you provide me with a quick example of how to to a time out to try?

Bruce
- 20th August 2010, 18:17
Hi Malc,

There's an example in the manual, but it works like this;

HSERIN 100,Timesup,[B0]

Timesup:
do something here is data not received

If no character is received in B0 within 100mS it jumps to Timesup.

malc-c
- 20th August 2010, 19:36
cheers Bruce...

Sorry, heat of the moment, quicker to ask than dig out the manual !

malc-c
- 20th August 2010, 20:36
Bruce,

One other thing that has come to light is that I need clear the buffer after


HSEROUT [dec StopHour[0],dec StopMin[0],dec StopHour[1],dec StopMin[1],dec StopHour[2],dec StopMin[2],dec StopHour[3],dec StopMin[3]


I gather this is required so that it places the correct variable in the right location in the application.

Any ideas

Bruce
- 20th August 2010, 23:15
I'm not 100% sure what you're asking Malc?

malc-c
- 21st August 2010, 11:12
To be honest I'm not sure either - I thought if you sent A,B,C through the port it would just loop that over and over again... do PICs have buffers ? I thought they sent data straight out and in ? but then I'm really getting out of my depth with this.

malc-c
- 21st August 2010, 12:25
Whilst undertaking several hours googling I came across a forum that contained a simple example from a two year old post of using VB.net to communicate with a PIC micro using PBP. So far I'm managing to adapt it to include a combo box to choose the comm port and retrieve a set of data from my PIC.

For reference here is the VB code


Imports System.IO
Imports System.IO.Ports
Imports System.Net
Imports System.Data
Imports System
Imports System.Windows.Forms
Imports System.Threading
Imports System.Text


Public Class mMain

Dim WithEvents serPort As New IO.Ports.SerialPort
Dim myStringBuilder As New StringBuilder

Private Sub mMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
For i As Byte = 0 To My.Computer.Ports.SerialPortNames.Count - 1
Me.ComboBox1.Items.Add(My.Computer.Ports.SerialPor tNames(i))
Next i

serPort.BaudRate = 115200
serPort.DataBits = 8
serPort.Parity = Parity.None
serPort.StopBits = StopBits.One

butConnect.Enabled = True
butDisConnect.Enabled = False
End Sub

Private Sub butConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butConnect.Click
If (serPort.IsOpen = False) Then
Try
serPort.Open()

lstData.Items.Clear()
myStringBuilder = New StringBuilder 'Clear any old data

butConnect.Enabled = False
butDisConnect.Enabled = True
Catch ex As Exception
'Routine to process exceptions like port already open etc.
MsgBox("Exception error")
End Try
End If
End Sub

Private Sub butDisConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butDisConnect.Click
If (serPort.IsOpen = True) Then
serPort.Close()
butDisConnect.Enabled = False
butConnect.Enabled = True
End If
End Sub

Private Sub serPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles serPort.DataReceived
Try
myStringBuilder.Append(serPort.ReadExisting())
Me.Invoke(New EventHandler(AddressOf update_Data))
Catch ex As Exception
MsgBox("Data Error")
End Try
End Sub

Private Sub update_Data()
lstData.Items.Add(myStringBuilder.ToString)
myStringBuilder = New StringBuilder 'Flush the old data
End Sub
End Class


I designed a form to suit the different buttons and combo boxes and this was the result.

http://micro-heli.co.uk/comstest.jpg

The data in the list box came from this section of PBP code



Hserout [DEC Temperatures(0)]
Hserout [DEC Temperatures(1)]
Hserout [DEC Temperatures(2)]
Hserout [DEC Temperatures(3)]
hserout [10]


And as I only have one sensor out of four connected to the input associated with Temperature(2) in use the value of 002610, 002680 etc is right and reflects the 26.1C (rising).

However I would like to split this and place the result into 4 separate text boxes, ie so textbox1 will be updated with just Temperature(0), Textbox2 with Temperature(1) etc. Is there any modification I can do to the PBP code to separate the string to do this.

I know there has been some concerns about discussing VB code on this forum, but IMO when it's related to such a topic this thread covers I feel that it's justified.

HenrikOlsson
- 21st August 2010, 13:35
Hi Malc,
My VB is very rusty at the moment but have a look at the Split function in VB. It can be used to split a single string into separate strings (an array of strings actually) and you can specify the delimiter used. So if you send your values as text (which you are at the moment) separated by a comma you can use split the recived string into separate strings which you can the us to populate the textboxes.

If your string as read from the serial port object (let's call it RxString) looks like:
002610,002660,002680,002680
Then something like MyArrayOfStrings = Split (RxString, ",") will return 002610 in the first element of MyArrayOfStrings, 002660 in the second and so on. You can then do something like myTextBox1.Text=MyArrayOfStrings(0)

This is all untested but lookup Split in MSDN and string handling/parsing in general.

/Henrik.

malc-c
- 21st August 2010, 14:03
Thanks Henrik,

I get the gist of what you have said, and I'll have a search for that expression. I must admit the syntax of VB is somewhat alien to me :eek:

malc-c
- 21st August 2010, 15:46
Guys, one further thing... when there is no sensor connected the value for say Temperatures(0) will be 0. When present it sends the temperature as a three digit value, eg 25.7c would be sent as 257. I really need to send a zero value as 000 and not a single 0,

any ideas ?

HenrikOlsson
- 21st August 2010, 16:23
Hi,
If you HSEROUT DEC3 Temperatures(0) it will write three digits, ie. 000 if the value is 0.

/Henrik.

malc-c
- 21st August 2010, 21:02
Thankyou - works a treat

gadelhas
- 21st August 2010, 21:06
Hi malc-c;

Hi use a function in VB, that does do the job, that you want, but you must send to VB more things;

You are sending 4 temperatures, i supose from 4 diferent sensors, 1 temperatura measure for each sensor.
So if you put something before sendig the temperatures to identify de sensor, like this for exemple;
You are Sending;
002610
002660
002680
002680

Ff you send;
S1002610
S2002660
S3002680
S4002680

The 2 first chars, are the ID of the sensor, and the 6 next chars are the temperature.

Now it's easy to separate them in VB, with the function "Mid",
On the event Data Received, you must do something like this;


Private Sub DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim buffer As String

buffer = SerialPort1.ReadExisting

If Mid(buffer, 1, 2) = "S1" Then
Label1.Text = Mid(buffer, 3, 6) ' label to show the temperature of 1º sensor
End If

If Mid(buffer, 1, 2) = "S2" Then
Label2.Text = Mid(buffer, 3, 6) ' label to show the temperature of 2º sensor
End If

If Mid(buffer, 1, 2) = "S3" Then
Label3.Text = Mid(buffer, 3, 6) ' label to show the temperature of 3º sensor
End If

If Mid(buffer, 1, 2) = "S4" Then
Label4.Text = Mid(buffer, 3, 6) ' label to show the temperature of 4º sensor
End If
End Sub


You can use it too in a Select case, and you should put a try....cath too.

If you don't understanding something, please tell me.

malc-c
- 22nd August 2010, 10:35
That sounds promising.

At the moment I've used Henriks suggestion to send three digits per record which helps with the formatting when the data is received by the application written by a chap from another forum who offered to help (he used liberty basic). However I'm trying to learn VB so your suggestion will help (I'm running two versions of PBP code side by side so I can develop either one :) )

At the moment the PIC sends data as


Hserout [DEC3 Temperatures(0)]
Hserout [DEC3 Temperatures(1)]
Hserout [DEC3 Temperatures(2)]
Hserout [DEC3 Temperatures(3)]

HSEROUT [dec3 normtemp[0]]
HSEROUT [dec3 normtemp[1]]
HSEROUT [dec3 normtemp[2]]
HSEROUT [dec3 normtemp[3]]

Hserout [dec3 alarmlow[0]]
Hserout [dec3 alarmlow[1]]
Hserout [dec alarmlow[2]]
Hserout [dec alarmlow[3]]

Hserout [dec3 alarmhigh[0]]
Hserout [dec3 alarmhigh[1]]
Hserout [dec3 alarmhigh[2]]
Hserout [dec3 alarmhigh[3]]

hserout [#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]
hserout [#StartHour[1] DIG 1,#StartHour[1] DIG 0,#StartMin[1] DIG 1,#StartMin[1] DIG 0]
hserout [#StartHour[2] DIG 1,#StartHour[2] DIG 0,#StartMin[2] DIG 1,#StartMin[2] DIG 0]
hserout [#StartHour[3] DIG 1,#StartHour[3] DIG 0,#StartMin[3] DIG 1,#StartMin[3] DIG 0]

hserout [#StopHour[0] DIG 1,#StopHour[0] DIG 0,#StopMin[0] DIG 1,#StopMin[0] DIG 0]
hserout [#StopHour[1] DIG 1,#StopHour[1] DIG 0,#StopMin[1] DIG 1,#StopMin[1] DIG 0]
hserout [#StopHour[2] DIG 1,#StopHour[2] DIG 0,#StopMin[2] DIG 1,#StopMin[2] DIG 0]
hserout [#StopHour[3] DIG 1,#StopHour[3] DIG 0,#StopMin[3] DIG 1,#StopMin[3] DIG 0]

Hserout [dec3 Droptemp[0]]
Hserout [dec3 Droptemp[1]]
Hserout [dec3 Droptemp[2]]
Hserout [dec3 Droptemp[3]]

hserout [#lightsetHR[0] DIG 1,#lightsetHR[0] DIG 0,#lightsetMN[0] DIG 1,#lightsetMN[0] DIG 0]
hserout [#lightsetHR[1] DIG 1,#lightsetHR[1] DIG 0,#lightsetMN[1] DIG 1,#lightsetMN[1] DIG 0]
hserout [#lightsetHR[2] DIG 1,#lightsetHR[2] DIG 0,#lightsetMN[2] DIG 1,#lightsetMN[2] DIG 0]
hserout [#lightsetHR[3] DIG 1,#lightsetHR[3] DIG 0,#lightsetMN[3] DIG 1,#lightsetMN[3] DIG 0]

hserout [#lightoffHR[0] DIG 1,#lightoffHR[0] DIG 0,#lightoffMN[0] DIG 1,#lightOFFMN[0] DIG 0]
hserout [#lightoffHR[1] DIG 1,#lightoffHR[1] DIG 0,#lightoffMN[1] DIG 1,#lightOFFMN[1] DIG 0]
hserout [#lightoffHR[2] DIG 1,#lightoffHR[2] DIG 0,#lightoffMN[2] DIG 1,#lightOFFMN[2] DIG 0]
hserout [#lightoffHR[3] DIG 1,#lightoffHR[3] DIG 0,#lightoffMN[3] DIG 1,#lightOFFMN[3] DIG 0]


I assume if I need to prefix each section to apply the same code to make each set of three digits get placed in the right text box ?

Also how would I modify the PBP code to send S1, S2 etc as part of the data, would it be "hserout [S1,dec3 temperatures[0]]

malc-c
- 25th August 2010, 22:43
Guys and Gals, need your help.

Through an other forum I've had the offer of some assistance from one of it's members. He has written an application (I believe it's in Liberty Basic) and so far we've got it to read the data stream from the PIC and display it in boxes

http://www.picbasic.co.uk/forum/attachment.php?attachmentid=4748&d=1282771417

We're now trying to get the application to send new values back to the PIC and this is where I need some guidance.

This is how he is sending data from the application


This version will send only the target temperatures.
It should send "S" followed by carriage return
Then it should send 12 digits (4 sensors * 3 digits) followed by carriage return
It should then wait 3 seconds to give you time to process stuff, then it will query everything and expect all 108 characters back.
It will then wait 4 seconds, and display what it received.


The PBP code contains the following sections



;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FOR TempWD = 0 TO 1000
IF RCIF THEN GOSUB Term_RX
PAUSE 1
NEXT TempWD
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


I've removed the original code that DT had written which displayed PID info via hyperterminal and replaced it with



Term_RX:
HSERIN [Char]
SELECT CASE Char
CASE "S","s"
Hserin [DEC3 normtemp(0)]
Hserin [DEC3 normtemp(1)]
Hserin [DEC3 normtemp(2)]
Hserin [DEC3 normtemp(3)]
END SELECT
return


But when the update button is clicked on the PC app the PIC appears to lock up.

I would welcome suggestions on what I'm doing wrong, or what's needed to work with the protocol my friend has evolved.

For reference here is the section that Darrel coded which used to set just one thermostat channel (ie would send just one value ) at a time



Term_RX:
HSERIN [Char]
SELECT CASE Char
CASE "S","s" ' Enter Setpoint
X=1 : Y=22 : GOSUB MoveCursor
HSEROUT ["Enter SetPoint ... (340=34.0",$F8,"): "]
HSERIN [DEC SetPoints(EditChannel)]
GOSUB TerminalMenu
SELECT CASE EditChannel
CASE 0 : Bvar = EE_SetPoint1
CASE 1 : Bvar = EE_SetPoint2
CASE 2 : Bvar = EE_SetPoint3
CASE 3 : Bvar = EE_SetPoint4
END SELECT

WRITE Bvar, WORD SetPoints(EditChannel)


I've got a routine within the code that contains SetPoints(0)=normtemp(0) etc so please don't get confused over the actual variables.

prstein
- 26th August 2010, 00:42
This version will send only the target temperatures.
It should send "S" followed by carriage return
Then it should send 12 digits (4 sensors * 3 digits) followed by carriage return
It should then wait 3 seconds to give you time to process stuff, then it will query everything and expect all 108 characters back.
It will then wait 4 seconds, and display what it received

Instead, try:

It should send "S"(single character, no carriage return)
It should wait for the PIC to reply with "K" (or your favorite acknowledge character)
Then it should send 12 digits (4 sensors * 3 digits) followed by carriage return
It should then wait 3 seconds to give you time to process stuff, then it will query everything and expect all 108 characters back.
It will then wait 4 seconds, and display what it received

Then in your main loop add something like:
nTest var byte


If PIR1.5 = 1 Then 'check to see if there is data in the serial buffer
HSERIN[nTest]
if nTest = "S" then
HSEROUT["K"] 'Let the PC know to start sending data
HSERIN[....all the rest of your stuff...]
endif
endif

I suspect the PIC appears to lock because it misses a byte. The above slows everything just a little and uses a positive acknowledgement to make sure everything is set.

Hope this helps somehow...

Best Regards,
Paul

malc-c
- 26th August 2010, 09:10
Paul,

Many thanks for the prompt reply.

One further question, in the original code there was the command to WRITE the result

WRITE Bvar, WORD SetPoints(EditChannel)

Would I need to use a similar line to update the normtemp variable with the data received from the PC, or will


Hserin [DEC3 normtemp(0)]
Hserin [DEC3 normtemp(1)]
Hserin [DEC3 normtemp(2)]
Hserin [DEC3 normtemp(3)]

suffice.

Also I'll add Bruce's time out as suggested, but should I also have the PIC send something at the end to tell the PC to signify data recived ?

prstein
- 26th August 2010, 18:15
Hello Malcom,

I confess the line "WRITE Bvar, WORD SetPoints(EditChannel)" doesn't make a lot of sense to me. I guess use it or not, depending on if you want non-volatile storage of the data. Just wait until *after* all the serial data is received as writing to the EEPROM takes (precious) time.

Regarding sending a final acknowledgement to the PC, I probably wouldn't bother if it was working well. Primarily because it can get complicated quickly between the PC program and PIC code, and it becomes extra frustrating if you are only writing one side and someone else is on the other.

Uncle Paul's general advice for serial ports:
0. Use the hardware USART/EUSART whenever possible. The software serial routines work well enough but are far trickier because there is no buffer.

1. Never try to read serial data until PIR1.5 = 1. Otherwise there is no data to be read and the firmware will hang. You can make this an interrupt source but I generally put it as an item in the main program loop.

2. Have the PC application send initially only 1 or 2 bytes of data to get the PIC's attention (because the PIC's serial buffer is 2 bytes so you are GUARANTEED to get that much successfully). Then the PC must patiently wait for the PIC to respond.

3. When the PIC is ready to receive the clump of data ("clump" means greater than two bytes), have it send a character or two back to the PC to signify "I'm ready."

4. After the PC receives the "I'm ready" message it should immediately send the data clump.

I don't work at all with VB or other forms of BASIC for the PC so I can't say anything specific about that. I generally use Delphi or C++, make use of the PC's multi-threading and serial buffer capabilities.

Hope I'm not missing the point here...8^)

Best Regards,
Paul

malc-c
- 26th August 2010, 20:30
Paul, thanks once again for the reply.

To simplify the testing between the applicatication this chap in Canada has written and my PBP code I've gone back to basics and written a simple test application that simply sends the output to the PC and then test the updating from the PC application.



;----[USART defines]--------------------------------------------------------
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 25 ' 115200 Baud @ 48MHz, 0.16%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ColumnWidth CON 10


TempWD VAR WORD
RCIF VAR PIR1.5 ' USART receive flag
GIE VAR INTCON.7



alarmhigh VAR WORD[4] ' used to store the desired high temp alarm values
alarmhigh1 VAR alarmhigh[0]
alarmhigh2 VAR alarmhigh[1]
alarmhigh3 VAR alarmhigh[2]
alarmhigh4 VAR alarmhigh[3]

alarmlow VAR WORD[4] ' used to store the desired low temp alarm values
alarmlow1 VAR alarmlow[0]
alarmlow2 VAR alarmlow[1]
alarmlow3 VAR alarmlow[2]
alarmlow4 VAR alarmlow[3]


lightsetHR VAR WORD[4] ' user to set light on hour
lightsetHR1 VAR lightsetHR[0]
lightsetHR2 VAR lightsetHR[1]
lightsetHR3 VAR lightsetHR[2]
lightsetHR4 VAR lightsetHR[3]

lightsetMN VAR WORD[4]
lightsetMN1 VAR lightsetMN[0]
lightsetMN2 VAR lightsetMN[1]
lightsetMN3 VAR lightsetMN[2]
lightsetMN4 VAR lightsetMN[3]

lightoffHR VAR WORD[4]
lightoffHR1 VAR lightoffHR[0]
lightoffHR2 VAR lightoffHR[1]
lightoffHR3 VAR lightoffHR[2]
lightoffHR4 VAR lightoffHR[3]

lightoffMN VAR WORD[4]
lightoffMN1 VAR lightoffMN[0]
lightoffMN2 VAR lightoffMN[1]
lightoffMN3 VAR lightoffMN[2]
lightoffMN4 VAR lightoffMN[3]

StartHour VAR WORD[4]
StartHour1 VAR StartHour[0]
StartHour2 VAR StartHour[1]
StartHour3 VAR StartHour[2]
StartHour4 VAR StartHour[3]

StartMin VAR WORD[4]
StartMin1 VAR StartMin[0]
StartMin2 VAR StartMin[1]
StartMin3 VAR StartMin[2]
StartMin4 VAR StartMin[3]

StopHour VAR WORD[4]
StopHour1 VAR StopHour[0]
StopHour2 VAR StopHour[1]
StopHour3 VAR StopHour[2]
StopHour4 VAR StopHour[3]

StopMin VAR WORD[4]
StopMin1 VAR StopMin[0]
StopMin2 VAR StopMin[1]
StopMin3 VAR StopMin[2]
StopMin4 VAR StopMin[3]

Droptemp VAR WORD[4]
droptemp1 var Droptemp[0]
droptemp2 var Droptemp[1]
droptemp3 var Droptemp[2]
droptemp4 var Droptemp[3]

Temperatures VAR WORD[4]
Temp1 VAR Temperatures[0]
Temp2 VAR Temperatures[1]
Temp3 VAR Temperatures[2]
Temp4 VAR Temperatures[3]


SetPoints VAR WORD[4] ' used to store the desired temperature setting
SetPoint1 VAR SetPoints[0]
SetPoint2 VAR SetPoints[1]
SetPoint3 VAR SetPoints[2]
SetPoint4 VAR SetPoints[3]

normtemp VAR WORD[4] ' used to store the desired temperature setting
normtemp1 VAR normtemp[0]
normtemp2 VAR normtemp[1]
normtemp3 VAR normtemp[2]
normtemp4 VAR normtemp[3]

FlashStar VAR BIT
nTest var byte
;---------------------------------------------------------------------

;set test values

Temperatures[0]=230
Temperatures[1]=240
Temperatures[2]=250
Temperatures[3]=260

normtemp[0]=240
normtemp[1]=250
normtemp[2]=260
normtemp[3]=270

alarmlow[0]=180
alarmlow[1]=180
alarmlow[2]=180
alarmlow[3]=180

alarmhigh[0]=360
alarmhigh[1]=360
alarmhigh[2]=360
alarmhigh[3]=360

StartHour1=00
StartHour2=00
StartHour3=00
StartHour4=00

StartMin1=00
StartMin2=00
StartMin3=00
StartMin4=00

StopHour1=00
StopHour2=00
StopHour3=00
StopHour4=00

StopMin1=00
StopMin2=00
StopMin3=00
StopMin4=00

Droptemp[0]=180
Droptemp[1]=180
Droptemp[2]=180
Droptemp[3]=180

lightsetHR1=00
lightsetHR2=00
lightsetMN1=00
lightsetMN2=00

lightoffHR1=00
lightoffHR2=00
lightoffMN1=00
lightoffMN2=00


;_________________________________________________ _____________

main:


If PIR1.5 = 1 Then 'check to see if there is data in the serial buffer
HSERIN[nTest]
if nTest = "S" then
gosub Term_RX
endif
endif


for tempwd = 0 to 3
setpoints(tempwd)=normtemp(tempwd)
next


LCDOut $FE,$D4+8,#setpoints(0)dig 2,#setpoints(0)dig 1,$FE,$D4+11,#setpoints(1)dig 2,#setpoints(1)dig 1 ' show current set temperatures
LCDOut $FE,$D4+14,#setpoints(2)dig 2,#setpoints(2)dig 1,$FE,$D4+17,#setpoints(3)dig 2,#setpoints(3)dig 1
LCDOUT $FE,$80 + 18,("*"&FlashStar*$FF)|(" "&~(FlashStar*$FF)) ; flash a star to show sample time, but used to indicate Alarm settings monitored
FlashStar = !FlashStar


Hserout [DEC3 Temperatures[0]]
Hserout [DEC3 Temperatures[1]]
Hserout [DEC3 Temperatures[2]]
Hserout [DEC3 Temperatures[3]]

HSEROUT [dec3 normtemp[0]]
HSEROUT [dec3 normtemp[1]]
HSEROUT [dec3 normtemp[2]]
HSEROUT [dec3 normtemp[3]]

Hserout [dec3 alarmlow[0]]
Hserout [dec3 alarmlow[1]]
Hserout [dec alarmlow[2]]
Hserout [dec alarmlow[3]]

Hserout [dec3 alarmhigh[0]]
Hserout [dec3 alarmhigh[1]]
Hserout [dec3 alarmhigh[2]]
Hserout [dec3 alarmhigh[3]]

hserout [#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]
hserout [#StartHour[1] DIG 1,#StartHour[1] DIG 0,#StartMin[1] DIG 1,#StartMin[1] DIG 0]
hserout [#StartHour[2] DIG 1,#StartHour[2] DIG 0,#StartMin[2] DIG 1,#StartMin[2] DIG 0]
hserout [#StartHour[3] DIG 1,#StartHour[3] DIG 0,#StartMin[3] DIG 1,#StartMin[3] DIG 0]

hserout [#StopHour[0] DIG 1,#StopHour[0] DIG 0,#StopMin[0] DIG 1,#StopMin[0] DIG 0]
hserout [#StopHour[1] DIG 1,#StopHour[1] DIG 0,#StopMin[1] DIG 1,#StopMin[1] DIG 0]
hserout [#StopHour[2] DIG 1,#StopHour[2] DIG 0,#StopMin[2] DIG 1,#StopMin[2] DIG 0]
hserout [#StopHour[3] DIG 1,#StopHour[3] DIG 0,#StopMin[3] DIG 1,#StopMin[3] DIG 0]

Hserout [dec3 Droptemp[0]]
Hserout [dec3 Droptemp[1]]
Hserout [dec3 Droptemp[2]]
Hserout [dec3 Droptemp[3]]

hserout [#lightsetHR[0] DIG 1,#lightsetHR[0] DIG 0,#lightsetMN[0] DIG 1,#lightsetMN[0] DIG 0]
hserout [#lightsetHR[1] DIG 1,#lightsetHR[1] DIG 0,#lightsetMN[1] DIG 1,#lightsetMN[1] DIG 0]


hserout [#lightoffHR[0] DIG 1,#lightoffHR[0] DIG 0,#lightoffMN[0] DIG 1,#lightOFFMN[0] DIG 0]
hserout [#lightoffHR[1] DIG 1,#lightoffHR[1] DIG 0,#lightoffMN[1] DIG 1,#lightOFFMN[1] DIG 0]

pause 200

goto main


Term_RX:
HSERin [dec3 normtemp[0]]
return


The application is simply sending S followed by three digits for normtemp[0] in DEC format, with no carriage returns - However when I click the update button of the application the PIC freezes for around 10 min. I've proved the PIC is responding to the PC app by changing the "S" to "X" (or any other character) which is ignored when the update button is pressed.

Unfortunately given the time difference (I'm in the UK he's in Canada) the logistics of implementing the suggestions of handshaking the way you suggest is not forthcoming.

Any suggestions

prstein
- 27th August 2010, 01:09
Hi Malcom,

Try changing the end of your code to this:

Term_RX:
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
RETURN
RX_Bombed:
HSEROUT ["Term_RX bombed out, all we got was", dec TempWD,13,10]
return

This should at least provide some insight into what's going on inside the PIC.

In your test application you ought to put a pause of at least 10 msec or so between when the "S" and the rest of the data are sent. You could also probably test this using the Serial Communicator inside of MicroCode Studio, if you have that. Hyperterm would also work.

I couldn't find your OSC define in this thread. Which oscillator speed are you using?

Oh, and DOH! I just recalled that I think you "terminate" the DEC3 by sending something that isn't a numeric ASCII character. Try sending a carriage return or a line feed after the 3-character value.

Best Regards,
Paul

malc-c
- 28th August 2010, 17:04
This is really doing my head in... My friends application simply sends Q on launch, and the S+three digits representing the new value for just one variable followed by Q. Yet I keep getting incorrect values in the receive variable.

Here's the test code. For testing purpose all the values for each variable is fixed to populate his PC application. The only variable that is updated is the Target Temperature for Unit 1.



ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM


DEFINE OSC 48 ; uses 12Mhz xtal

ADCON1 = $0F
clear

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us


;----[Port settings]----------------------------------------------------

TRISA = %11001111
TRISB = %00000000
TRISD = %00001111
CMCON = 7 ' disable Comparators

;----[USART defines]--------------------------------------------------------
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 25 ' 115200 Baud @ 48MHz, 0.16%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ColumnWidth CON 10


TempWD VAR WORD
RCIF VAR PIR1.5 ' USART receive flag
GIE VAR INTCON.7

tr var byte

alarmhigh VAR WORD[4] ' used to store the desired high temp alarm values
alarmhigh1 VAR alarmhigh[0]
alarmhigh2 VAR alarmhigh[1]
alarmhigh3 VAR alarmhigh[2]
alarmhigh4 VAR alarmhigh[3]

alarmlow VAR WORD[4] ' used to store the desired low temp alarm values
alarmlow1 VAR alarmlow[0]
alarmlow2 VAR alarmlow[1]
alarmlow3 VAR alarmlow[2]
alarmlow4 VAR alarmlow[3]


lightsetHR VAR WORD[4] ' user to set light on hour
lightsetHR1 VAR lightsetHR[0]
lightsetHR2 VAR lightsetHR[1]
lightsetHR3 VAR lightsetHR[2]
lightsetHR4 VAR lightsetHR[3]

lightsetMN VAR WORD[4]
lightsetMN1 VAR lightsetMN[0]
lightsetMN2 VAR lightsetMN[1]
lightsetMN3 VAR lightsetMN[2]
lightsetMN4 VAR lightsetMN[3]

lightoffHR VAR WORD[4]
lightoffHR1 VAR lightoffHR[0]
lightoffHR2 VAR lightoffHR[1]
lightoffHR3 VAR lightoffHR[2]
lightoffHR4 VAR lightoffHR[3]

lightoffMN VAR WORD[4]
lightoffMN1 VAR lightoffMN[0]
lightoffMN2 VAR lightoffMN[1]
lightoffMN3 VAR lightoffMN[2]
lightoffMN4 VAR lightoffMN[3]

StartHour VAR WORD[4]
StartHour1 VAR StartHour[0]
StartHour2 VAR StartHour[1]
StartHour3 VAR StartHour[2]
StartHour4 VAR StartHour[3]

StartMin VAR WORD[4]
StartMin1 VAR StartMin[0]
StartMin2 VAR StartMin[1]
StartMin3 VAR StartMin[2]
StartMin4 VAR StartMin[3]

StopHour VAR WORD[4]
StopHour1 VAR StopHour[0]
StopHour2 VAR StopHour[1]
StopHour3 VAR StopHour[2]
StopHour4 VAR StopHour[3]

StopMin VAR WORD[4]
StopMin1 VAR StopMin[0]
StopMin2 VAR StopMin[1]
StopMin3 VAR StopMin[2]
StopMin4 VAR StopMin[3]

Droptemp VAR WORD[4]
droptemp1 var Droptemp[0]
droptemp2 var Droptemp[1]
droptemp3 var Droptemp[2]
droptemp4 var Droptemp[3] ; these will be set via pots

Temperatures VAR WORD[4]
Temp1 VAR Temperatures[0]
Temp2 VAR Temperatures[1]
Temp3 VAR Temperatures[2]
Temp4 VAR Temperatures[3]

spModes VAR BYTE[4] ' controls how set point is adjusted PC or POT
spMode1 VAR spModes[0]
spMode2 VAR spModes[1]
spMode3 VAR spModes[2]
spMode4 VAR spModes[3]

SetPoints VAR WORD[4] ' used to store the desired temperature setting
SetPoint1 VAR SetPoints[0]
SetPoint2 VAR SetPoints[1]
SetPoint3 VAR SetPoints[2]
SetPoint4 VAR SetPoints[3]

normtemp VAR WORD[4] ' used to store the desired temperature setting
normtemp1 VAR normtemp[0]
normtemp2 VAR normtemp[1]
normtemp3 VAR normtemp[2]
normtemp4 VAR normtemp[3]

FlashStar VAR BIT
nTest var byte
temphold var byte
temp var byte
;---------------------------------------------------------------------

;set test values

Temperatures[0]=230
Temperatures[1]=240
Temperatures[2]=250
Temperatures[3]=260

normtemp[0]=240
normtemp[1]=250
normtemp[2]=260
normtemp[3]=270

alarmlow[0]=180
alarmlow[1]=180
alarmlow[2]=180
alarmlow[3]=180

alarmhigh[0]=360
alarmhigh[1]=360
alarmhigh[2]=360
alarmhigh[3]=360

StartHour1=00
StartHour2=00
StartHour3=00
StartHour4=00

StartMin1=00
StartMin2=00
StartMin3=00
StartMin4=00

StopHour1=00
StopHour2=00
StopHour3=00
StopHour4=00

StopMin1=00
StopMin2=00
StopMin3=00
StopMin4=00

Droptemp[0]=180
Droptemp[1]=180
Droptemp[2]=180
Droptemp[3]=180

lightsetHR1=00
lightsetHR2=00
lightsetMN1=00
lightsetMN2=00

lightoffHR1=00
lightoffHR2=00
lightoffMN1=00
lightoffMN2=00


;_________________________________________________ _____________

main:

FOR TempWD = 0 TO 1000
IF RCIF=1 THEN GOSUB Term_RX
PAUSE 2
NEXT TempWD


setpoints(0)=normtemp(0)



LCDOut $FE,$D4,#setpoints(0)dig 2,#setpoints(0)dig 1,#setpoints(0)dig 0
FlashStar = !FlashStar
pause 200
goto main

send:
Hserout [DEC3 Temperatures[0]]
Hserout [DEC3 Temperatures[1]]
Hserout [DEC3 Temperatures[2]]
Hserout [DEC3 Temperatures[3]]

HSEROUT [dec3 normtemp[0]]
HSEROUT [dec3 normtemp[1]]
HSEROUT [dec3 normtemp[2]]
HSEROUT [dec3 normtemp[3]]

Hserout [dec3 alarmlow[0]]
Hserout [dec3 alarmlow[1]]
Hserout [dec alarmlow[2]]
Hserout [dec alarmlow[3]]

Hserout [dec3 alarmhigh[0]]
Hserout [dec3 alarmhigh[1]]
Hserout [dec3 alarmhigh[2]]
Hserout [dec3 alarmhigh[3]]

hserout [#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]
hserout [#StartHour[1] DIG 1,#StartHour[1] DIG 0,#StartMin[1] DIG 1,#StartMin[1] DIG 0]
hserout [#StartHour[2] DIG 1,#StartHour[2] DIG 0,#StartMin[2] DIG 1,#StartMin[2] DIG 0]
hserout [#StartHour[3] DIG 1,#StartHour[3] DIG 0,#StartMin[3] DIG 1,#StartMin[3] DIG 0]

hserout [#StopHour[0] DIG 1,#StopHour[0] DIG 0,#StopMin[0] DIG 1,#StopMin[0] DIG 0]
hserout [#StopHour[1] DIG 1,#StopHour[1] DIG 0,#StopMin[1] DIG 1,#StopMin[1] DIG 0]
hserout [#StopHour[2] DIG 1,#StopHour[2] DIG 0,#StopMin[2] DIG 1,#StopMin[2] DIG 0]
hserout [#StopHour[3] DIG 1,#StopHour[3] DIG 0,#StopMin[3] DIG 1,#StopMin[3] DIG 0]

Hserout [dec3 Droptemp[0]]
Hserout [dec3 Droptemp[1]]
Hserout [dec3 Droptemp[2]]
Hserout [dec3 Droptemp[3]]

hserout [#lightsetHR[0] DIG 1,#lightsetHR[0] DIG 0,#lightsetMN[0] DIG 1,#lightsetMN[0] DIG 0]
hserout [#lightsetHR[1] DIG 1,#lightsetHR[1] DIG 0,#lightsetMN[1] DIG 1,#lightsetMN[1] DIG 0]


hserout [#lightoffHR[0] DIG 1,#lightoffHR[0] DIG 0,#lightoffMN[0] DIG 1,#lightOFFMN[0] DIG 0]
hserout [#lightoffHR[1] DIG 1,#lightoffHR[1] DIG 0,#lightoffMN[1] DIG 1,#lightOFFMN[1] DIG 0]



return

Term_RX:
HSERIN[nTest]
SELECT CASE nTest
CASE "S"
HSERIN [normtemp[0]]
setpoints(0)=normtemp[0]
END SELECT
gosub send
return



On booting the PIC it displays the value of normtemp[0] as 240 on the LCD. I've used a serial port monitor and when the application is launched the port sniffer confirms that Q was sent and the PIC dumped the string of values to the port, which the application pics up and populates the text boxes correctly.

http://micro-heli.co.uk/Applaunch.jpg

The application has been written to allow the user to enter the desired target temperature directly in the associated text box as required such as 45.2 and then click on the UPDATE button. This then sends S followed by the new value as a three digit number in the same format as the PBP code. This can be confirmed by the port sniffer

http://micro-heli.co.uk/apperror.jpg

However, the LCD display then reads 052, and this is then sent back to the PC application (as can be seen if you follow through the digits in the com sniffer top window.

http://micro-heli.co.uk/RHC.jpg

I think by fluke I did manage to get it to work once where the normtemp[0] variable was correctly updated, but that was after a restart of both the windows application and the PIC. What's been suggested is that I need the PBP code to check that the PICs buffer is empty, but I'm not sure on how to best do that.

Eventually we need to be able to update all the values in the rest of the boxes, and it my understanding my friends application will simply send all the values back in one data stream that will match the same as that transmitted (less the first 12 digits as it doesn't need to update the current temperatures - this is a one way transmission from the PIC). Thus the RX section will have HSERIN for each variables as per the HSEROUT section - will this compound the problem or can someone suggest a better way of doing this.

HenrikOlsson
- 28th August 2010, 17:38
Hi Malcolm,
I think you need to do:

HSERIN [DEC3 NORMTEMP[0]]

/Henrik.

EDIT: Look at post #22 up above, Paul's already covered it, are you saying that IT isn't working either?

malc-c
- 28th August 2010, 19:09
Hi Henrik,

I've tried that and it does make a difference, it drops it down to 005 rather than 051, so DEC3 tends to shift things one place to the right.

I've changed Pauls suggestion so it displays the bombed out value on the LCD



Term_RX:
HSERIN[nTest]
SELECT CASE nTest
CASE "S"
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
gosub send
RETURN
RX_Bombed:
lcdOUT $FE,$D4,"all we got was", dec TempWD
end select
return


And the first time I launched the application and booted the PIC I got a result on the screen. I then entered another value and the LCD reported that it bombed with a result of 0. This happens on all subsequent tries, even with the PIC and application being re-started - it seems I get a result first time the PC application is launched.... but no every time - it seems random.... would reducing the baud rate give better results ?

HenrikOlsson
- 28th August 2010, 19:37
Hi,
I just tried a somewhat modifed version here (to be able to test on my hardware).

Term_RX:
HSERIN[nTest]
SELECT CASE nTest
CASE "S"
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
gosub send
Goto Term_Rx
RX_Bombed:
TimeoutCount = TimeOutCount + 1
lcdOUT $FE,1,"all we got was", dec TempWD,", ", DEC TimeOutCount

end select

Goto Term_Rx

Send:
HSEROUT [DEC normtemp[0],10]
RETURN
This seems to work just fine when sending from the serial terminal. The only thing is that there will not be a value assigned to TempWd if HSERIN times out, as can be seen it screenshot.

Question is if the problem is with the PIC code or with the PC application....

/Henrik.

/Henrik.

malc-c
- 28th August 2010, 19:55
Question is if the problem is with the PIC code or with the PC application....



/Henrik.

Uhmm I'm beginning to wonder if it's my PC or possibly Vista ?

I modified the code as suggested (removing the parts that were adjusted for your hardware) and using the serial comms in MCS sent S777 and the LCD reported 0 received by the PIC.

HenrikOlsson
- 29th August 2010, 08:42
Hi,
That's weird.... As long as I send Snnn here I can't seem to make it fail. If I send Snn[CR] then it shows nn because apparently HSERIN terminates the reception when it sees the [CR], however if I just send Snn it times out properly. If I then return to properly sending Snnn it works fine again.

Try calling this:

FlushBuffer:
While PIR1.5
HSERIN [TempWd]
WEND
TempWd=0
LCDOUT $FE,1,"Buffer flushed"
RETURN
At start up and from the timeout routine, it should flush the receive buffer.

/Henrik.

malc-c
- 29th August 2010, 12:12
Well I have no idea what's happening. I added the sub routine at the end of the code and then called it thus


Term_RX:

TempWD = 0
HSERIN[nTest]
SELECT CASE nTest
CASE "S"
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
gosub send

end select
RETURN
RX_Bombed:
gosub FlushBuffer
LCDOUT $FE,$80
lcdOUT $FE,$D4,"all we got was", dec TempWD
LCDOUT $FE,$80
return


FlushBuffer:
While PIR1.5
HSERIN [TempWd]
WEND
TempWd=0
LCDOUT $FE,1,"Buffer flushed"
RETURN


And the subroutine gets called as part of the initialization before it checks the port in the main program loop. The results when using the serial coms util in MCS were again random. I managed three changes in a row before the LCD reported 0 received. I tried the application written in LB and that too had similar results. I've also tried this application from my Son's PC and got the same result, so that would rule out my PC's port as the issue.

I've re-loaded one of the versions which included code written by DT which uses hyperterm to display data and allow variables to be changed one at a time and that functions just fine so that would suggest the coms on the EasyPIC5 board and the PIC don't have an issues.

One thing I have noticed, When I simplify the code to simply read the variable


Term_RX:
HSERIN[nTest]
SELECT CASE nTest
CASE "Q"
gosub send
CASE "S"
gosub update
End select
Return

update:

HSERIN [DEC normtemp[0]]
setpoints(0)=normtemp[0]
gosub flushbuffer:

return


and send say S789 from the serial communicator the LCD changes but displays 007 as if it's picked up the 1st byte and then ignored the rest. If I change the HSERIN line by removing DEC statement the LCD displays 055 ???? - I was expecting at least 078 ???

I would welcome any further suggestions

HenrikOlsson
- 29th August 2010, 12:31
Hi,
Try running it a slower baud rate, just as a test - say 2400 baud.


One thing I have noticed, When I simplify the code to simply read the variable and send say S789 from the serial communicator the LCD changes but displays 007 as if it's picked up the 1st byte and then ignored the rest.
It is because you just say HSERIN [DEC Normtemp[0]] so PBP grabs the first character which is 7 - change that to DEC3 to grab three digits and properly convert it to 789.

If I change the HSERIN line by removing DEC statement the LCD displays 055 ???? - I was expecting at least 078 ???
And this is because you removed the DEC modifier so PBP again grabs one character and 55 is the ASCII code for "7".

You have to remember that the PC (in this case) doesn't send the "value" 789 it sends the the individual digits representing the number as text "S", "7", "8", "9" if you look at that transmision with your serial port monitor you'll see that what is sent is 83 55 56 57 which are the ASCII codes for S789.

The DEC modifier converts the text representation of the value into an actual value. If you remove it the value stored in the variable will be the value received - which is 55 when you send "7".

/Henrik.

malc-c
- 29th August 2010, 14:43
Full Code:



ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM


DEFINE OSC 48 ; uses 12Mhz xtal

ADCON1 = $0F
clear

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us


;----[Port settings]----------------------------------------------------

TRISA = %11001111
TRISB = %00000000
TRISD = %00001111
CMCON = 7 ' disable Comparators

;----[USART defines]--------------------------------------------------------


DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 25 ' 115200 Baud @ 48MHz, 0.16%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
ColumnWidth CON 10


TempWD VAR WORD
RCIF VAR PIR1.5 ' USART receive flag
GIE VAR INTCON.7

tr var byte



normtemp VAR WORD[4] ' used to store the desired temperature setting
normtemp1 VAR normtemp[0]
normtemp2 VAR normtemp[1]
normtemp3 VAR normtemp[2]
normtemp4 VAR normtemp[3]

nTest var byte
temphold var byte
temp var byte

TimeoutCount var byte
;---------------------------------------------------------------------

;set test values


normtemp[0]=240
normtemp[1]=250
normtemp[2]=260
normtemp[3]=270



;_________________________________________________ _____________


gosub FlushBuffer

main:

FOR TempWD = 0 TO 1000
IF RCIF=1 THEN GOsub Term_RX
PAUSE 1
NEXT TempWD

pause 200
goto main



Term_RX:
HSERIN[nTest]
SELECT CASE nTest
CASE "S"
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
gosub send
Goto Term_Rx
RX_Bombed:
TimeoutCount = TimeOutCount + 1
lcdOUT $FE,1,"all we got was", dec TempWD,", ", DEC TimeOutCount

end select

Goto Term_Rx

Send:
HSEROUT [DEC normtemp[0],10]
setpoints(0)=normtemp[0]
LCDOut $FE,$D4,#setpoints(0)dig 2,#setpoints(0)dig 1,#setpoints(0)dig 0
RETURN


FlushBuffer:
While PIR1.5
HSERIN [TempWd]
WEND
TempWd=0
LCDOUT $FE,1,"Buffer flushed"
RETURN



I tried this at 2400 baud (having use PIC multicalc to get the Uart setting) and it gave one error and then echoed all the subsequent entry's correctly. I then changed it back to 115200 and it works a treat :) - even with my friends application.

Henrick thanks for taking the time out to assist me with this, and for explaining the serial function in laymens terms, I have learnt a lot from your posts.

Now just got to amend the code so that it does the same for all the other variables :eek:

I think Charles was going to have his application send one long string of all the variables, maybe I should ask him if he can make it user selected so it updates just the one ?

malc-c
- 29th August 2010, 15:11
Uhmmm strange things.. I spoke too soon.

If I follow your example code


Term_RX:
HSERIN[nTest]
SELECT CASE nTest
CASE "S"
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
gosub send
Goto Term_Rx
RX_Bombed:
TimeoutCount = TimeOutCount + 1
lcdOUT $FE,1,"all we got was", dec TempWD,", ", DEC TimeOutCount

end select

Goto Term_Rx

FlushBuffer:
While PIR1.5
HSERIN [TempWd]
WEND
TempWd=0
LCDOUT $FE,1,"Buffer flushed"
RETURN


when the program 1st runs and detects somthing in the buffer it gosubs to Term_RX, but with the goto hi-lighted above the program then never returns to the main program... If I change this to go to main I'm back where I started from...

I guess I should ask Charles to design his application so that it opens a second window to do the updates, and when it opens that window it sends a Q or P or something which makes the PIC jump to the Term_RX section, and then sends another character when the updating window is closed (sort of click APPLY )

HenrikOlsson
- 29th August 2010, 15:34
Hi,
That goto was needed in order to test it at my end (I said I modified it), it was never my intention for you to copy/paste that code back into your application - sorry about that.

With this code:

main:
FOR TempWD = 0 TO 1000
IF RCIF=1 THEN GOsub Term_RX
PAUSE 1
NEXT TempWD
pause 200
goto main

You are looping around polling the RCIF flag 1000 times in one second (basically). But at 115200 baud you're sending ~11500 bytes or characters per second (one startbit, 8 databots, one stopbot = 10bits per character).

This means you're sending ~11.5 characters every millisecond. The PICs hardware buffer is only 2 levels deep so you're very likely to overrun the buffer before the HSERIN command is able to grab the data.

At 2400baud you're only sending 240 characters per second so your polling loop will have no problem catching the RCIF flag and jump to the Term_Rx routine before the buffer overruns.

Does that make sense?

/Henrik.

malc-c
- 29th August 2010, 17:28
Hi,

You are looping around polling the RCIF flag 1000 times in one second (basically). But at 115200 baud you're sending ~11500 bytes or characters per second (one startbit, 8 databots, one stopbot = 10bits per character).

This means you're sending ~11.5 characters every millisecond. The PICs hardware buffer is only 2 levels deep so you're very likely to overrun the buffer before the HSERIN command is able to grab the data.

At 2400baud you're only sending 240 characters per second so your polling loop will have no problem catching the RCIF flag and jump to the Term_Rx routine before the buffer overruns.

Does that make sense?

/Henrik.

Yes, somewhat - no wonder why I was having problems missing the data... so is it better to reduce the baud rate for the port or reduce the for next loop steps ?

HenrikOlsson
- 29th August 2010, 18:43
Hi Malcolm,
If the PC starts to send S789 right at the beginning of the Pause 1 statment all four bytes will have been sent before the PIC checks the RCIFlag and your data will be messed up. So, as you say, either check the flag more often or reduce the baudrate so that you are sure that a maximum of two characters can arrive while you are not watching - so to speak.

Actually, there can be two bytes in the buffer and a third on its way in without messing it up. But as soon as the last bit of that third byte is shifted in you're in trouble if there's no room in the two byte buffer.

Let me see if I've got the overall scheme correct.
** The PIC does its thing, running the PID and everything. Each time thru its main loop it checks the RCIFlag.
** The PC, when it needs attention sends a single character "Q" to the PIC and waits.
** The PIC sees the RCIFlag and gets the character (there's no problem here since a single character will sit in the buffer untill you get around to read it)
** The PIC compares the received character to "Q" and sends something back to say "OK, hit me" - it then goes to the loop we've been discussing.

That should work..... At 115200 baud two characters takes roughly 175us so you need to check the RCIF flag at least that often. I'd probably go with something like:

WaitHere:
For I = 0 to 10000
If RCIF = 1 then GOSUB Term_Rx
PauseUs 100
Next


Keep it up!
/Henrik.

malc-c
- 29th August 2010, 20:31
Hi Malcolm,


Let me see if I've got the overall scheme correct.
** The PIC does its thing, running the PID and everything. Each time thru its main loop it checks the RCIFlag.
** The PC, when it needs attention sends a single character "Q" to the PIC and waits.
** The PIC sees the RCIFlag and gets the character (there's no problem here since a single character will sit in the buffer untill you get around to read it)
** The PIC compares the received character to "Q" and sends something back to say "OK, hit me" - it then goes to the loop we've been discussing.


/Henrik.

Pretty much it. As far as I understand Charles has programmed his code to send Q when the program is first launched, this was so that we could use Q as a trigger to jump to a subroutine and have the PIC send the data string.... then the user over types the value in the target temperature box and then when the Update button is clicked it sends Snnn to the PIC, followed by Q to refresh the PC application.

I've tried migrating the test code over to the main code that you were involved in and have discovered one issue. On launching the application the LCD stops running, but I can set the temperature set point via the application on the PC, which upon pressing the Update button the value on the LCD changes to match. However whilst the application is still open the LCD is still not updated. If I then close the application it still locks up and I have to restart the PIC.

At the moment I've reduced the
FOR TempWD = 0 TO 1000
to
FOR TempWD = 0 TO 10
so at 115200 baud rate that should equate to 115 bytes as second (? yes)

If RCIF=1 it gosubs to the TERM_RX



Term_RX:
HSERIN [nTest]
SELECT CASE nTest
CASE "S"
TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
SetPoints(0)=normtemp[0]
goto Term_TX

return

RX_Bombed:
TimeoutCount = TimeOutCount + 1
end select
Goto Term_Rx


Term_TX is simply



Term_TX:

Hserout [DEC3 Temperatures(0)]
Hserout [DEC3 Temperatures(1)]
Hserout [DEC3 Temperatures(2)]
Hserout [DEC3 Temperatures(3)]

HSEROUT [dec3 normtemp[0]]
HSEROUT [dec3 normtemp[1]]
....
...
...... etc etc

gosub flushBuffer
goto main


If I close the down the application and even disconnect the cable from the EasyPIC board the PIC is still frozen....

Any idea ?

HenrikOlsson
- 29th August 2010, 21:20
Hi,
Changing the FOR-NEXT loop will only change how many times it loops around checking the RCIFlag and therefor the total time it spends waitng for it - not how often it checks it or how many bytes per second that is sent or received.

For 115200 baud you must check the RCIFlag at least once every ~170us so, like I showed you earlier:

For TempWd = 0 to 10000
If RCIF then GOSUB Term_Rx
PauseUs 100 '<----Note PauseUs, as in Pause micro seconds...
Next
Goto Main

This will check the RCIFlag every 100us and it will do it 10000 times, so all in all it will wait one second, if no data is received it'll jump to Main.

If you by, the LCD stops updating, mean that the data written to the LCD by the main program in the PIC it's because once the PIC sees the initial RCIF caused by the the "Q" beeing received the main code stops and jumps to your receive routines. It then stays there untill you return to the main program so the LCD can't update....



RX_Bombed:
TimeoutCount = TimeOutCount + 1
end select
Goto Term_Rx
Here, you probably don't want to jump back to Term_Tx but instead jump back to either your main program or RETURN depending on how you got to the routine in the first place. That should prevent the PIC from locking up. And you can remove the TeimOutCount thing, that was for my tests....

You need to implement some form of handshaking when the user presses Update in the application, simmilar to when the app is first started. The PC can't just dump data into the PIC since your application may be off doing something else and miss it. (Since you're not using interrupts).

Take a pen a piece of paper, think it thru.

/Henrik.

malc-c
- 29th August 2010, 21:26
Ok I see the logic behind the pause statement.

I've managed to resolve the stalling...



CASE "Q"
Goto Term_TX


Just placed that above the CASE "S" and now it works as it should .... strange how the logical things get overlooked !

malc-c
- 30th August 2010, 16:32
Need one final bit of assistance. We've made the changes to the PC application so that it sends the complete string back to the PIC. Q tells the PIC to send data, S tells it to expect data

QS350635250249250250250249250250250249000000000000 000000000000000000001501501501500000000000000000Q

This should then populate the variables as follows



[dec3 normtemp[0]]
[dec3 normtemp[1]]
[dec3 normtemp[2]]
[dec3 normtemp[3]]

[dec3 alarmlow[0]]
[dec3 alarmlow[1]]
[dec3 alarmlow[2]]
[dec3 alarmlow[3]]

[dec3 alarmhigh[0]]
[dec3 alarmhigh[1]]
[dec3 alarmhigh[2]]
[dec3 alarmhigh[3]]

[#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]
[#StartHour[1] DIG 1,#StartHour[1] DIG 0,#StartMin[1] DIG 1,#StartMin[1] DIG 0]
[#StartHour[2] DIG 1,#StartHour[2] DIG 0,#StartMin[2] DIG 1,#StartMin[2] DIG 0]
[#StartHour[3] DIG 1,#StartHour[3] DIG 0,#StartMin[3] DIG 1,#StartMin[3] DIG 0]

[#StopHour[0] DIG 1,#StopHour[0] DIG 0,#StopMin[0] DIG 1,#StopMin[0] DIG 0]
[#StopHour[1] DIG 1,#StopHour[1] DIG 0,#StopMin[1] DIG 1,#StopMin[1] DIG 0]
[#StopHour[2] DIG 1,#StopHour[2] DIG 0,#StopMin[2] DIG 1,#StopMin[2] DIG 0]
[#StopHour[3] DIG 1,#StopHour[3] DIG 0,#StopMin[3] DIG 1,#StopMin[3] DIG 0]

[dec3 Droptemp[0]]
[dec3 Droptemp[1]]
[dec3 Droptemp[2]]
[dec3 Droptemp[3]]

[#lightsetHR[0] DIG 1,#lightsetHR[0] DIG 0,#lightsetMN[0] DIG 1,#lightsetMN[0] DIG 0]
[#lightsetHR[1] DIG 1,#lightsetHR[1] DIG 0,#lightsetMN[1] DIG 1,#lightsetMN[1] DIG 0]

[#lightoffHR[0] DIG 1,#lightoffHR[0] DIG 0,#lightoffMN[0] DIG 1,#lightOFFMN[0] DIG 0]
[#lightoffHR[1] DIG 1,#lightoffHR[1] DIG 0,#lightoffMN[1] DIG 1,#lightOFFMN[1] DIG 0]


Now I've used the following to handle the import of things like normtemp etc and that work fine



TempWD = 0
HSERIN 1000,RX_Bombed,[DEC3 TempWD]
normtemp[0] = TempWD
SetPoints(0)=normtemp[0]


However I'm having issues formatting the HSERIN sections for the times such as lightsON and Lights OFF and StartHour etc, especially as these are just two digits 00 - 23 for hours and 00 - 59 for mins. MCS reports
Expected ']' but it doesn't hell me where, and adding them to most logical places (like at the end) still results in similar errors

Any ideas ?

malc-c
- 30th August 2010, 18:12
Any reason why


hserout [#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]


compiles, but


hserin [#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]


Throws up an "expected ]" error. I've tried adding ] to nearly all possible permutations and still can't get it nto compile

HenrikOlsson
- 30th August 2010, 18:47
Hi Malcolm,
You can get that error message when you've missed a comma somewhere in the HSERIN command, look carefully and I think you'll find it.

Anyway, I took a stab at it here and I think the following should do it:

'-------------------------------------------------------------------------------
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC3 NormTemp[Counter]]
NEXT
'-------------------------------------------------------------------------------
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC3 AlarmLow[Counter]]
NEXT
'-------------------------------------------------------------------------------
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC3 AlarmHigh[Counter]]
NEXT
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC2 StartHour[Counter], DEC2 StartMin[Counter]]
NEXT
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC2 StopHour[Counter], DEC2 StopMin[Counter]]
NEXT
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC3 DropTemp[Counter]]
NEXT
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
For Counter = 0 to 3
HSERIN 1000, RX_Bombed, [DEC2 LightSetHR[Counter], DEC2 LightSetMN[Counter]]
NEXT
'-------------------------------------------------------------------------------
It seems to work, I wrote up a bit of code to re-send all the variable back to PC and it looks like in the attached screenshot. Note that I'm only sending the "S" and I'm not waiting for that final "Q" in your datastream.

/Henrik.

PS. Here's the code I used to send everything back to the terminal, might be good for further debugging:

HSEROUT ["-------------------------------",10]
For Counter = 0 to 3
HSEROUT ["Normtemp ", #Counter, " : ", DEC3 Normtemp[counter],10]
HSEROUT ["AlarmHigh ",#Counter, " : ", Dec3 AlarmHigh[Counter],10]
HSEROUT ["AlarmLow ",#Counter, " : ", Dec3 AlarmLow[Counter],10]
HSEROUT ["Start ",#Counter, " : ", Dec2 StartHour[Counter],":", DEC2 StartMin,10]
HSEROUT ["Stop ",#Counter, " : ", Dec2 StopHour[Counter],":", DEC2 StopMin,10]
HSEROUT ["Droptemp ",#Counter," : ", DEC3 Droptemp[counter],10]
HSEROUT ["Light set ",#Counter, " : ", DEC2 LightSetHr, ":", Dec2 LightsetMn,10]
HSEROUT ["-------------------------------",10]
Next
HSEROUT ["T H A T ' S I T M A L C O L M",10,10]

HenrikOlsson
- 30th August 2010, 18:52
Hello again,
I didn't see your latest message before posting my previous.

It's not a comma missing in your HSERIN statement, however I don't think DIG can be used with HSERIN, only with HSEROUT - I think.

malc-c
- 30th August 2010, 19:25
Henrik,

As always, thanks for your help - that works a treat - THANK YOU !!!!!

malc-c
- 30th August 2010, 20:16
Just thought you might like to see the final result. I just hope that others searching or working on serial communications can make use of all that has gone on in this thread

http://www.picbasic.co.uk/forum/attachment.php?attachmentid=4757&d=1283195753

malc-c
- 14th September 2010, 22:11
Maybe I spoke too soon - seems that something corrupts the LCD after a set number of transfers.

Basically the PC applications sends a "Q" every 10 seconds which causes the PIC to respond by sending the stream of digits described above. On the 27th Q the LCD starts to display random characters, initially along the bottom line of the 4 line LCD.

Thinking it might be the application I used the serial port coms app from MCS and manually sent Q's to the PC. on the 27th the same thing happened....

Any ideas on where to start de-bugging ?

HenrikOlsson
- 15th September 2010, 09:09
Hi Malcolm,
Really hard to say. Is it repeatable, always 27 times? Is everything else OK, just the LCD acting up?

I think you're going to have to post some code.

Jerson
- 15th September 2010, 09:44
Hi Malc_c

I was curious to see this thread and got into this pretty late.

How big is the serial data packet that you send down to the PIC?
From the details you gave, I think you have problems PC->PIC (downstream)
If that is true, are you buffering your received characters on the PIC? If not, then the least you can do is make the PC space out the characters in time. Put a few mS gap between each character sent to the PIC to avoid losing characters on the PIC
How do you synch the receive to the start of the incoming stream of data? Do you have a synch character to look for?
It will be better to look over the whole code to find the problem.

Regards

malc-c
- 15th September 2010, 12:38
Hi and thanks for the advice. The PC application simply send "Q" to the PIC every 10 seconds. The PIC responds to the Q by sending the 100 odd digits for the variables as described in previous posts above. When the application is used to update or set the PIC, the application has an "update" button which sends an "S" followed by the same 100 odd digits, followed by a "Q" to read back the values just written. The application does not send variable data to the PIC at any other time.

I agree that it's difficult to diagnose what might be happening without the complete code - please drop me a PM with an e-mail address and I'll mail you the code.

Jerson
- 15th September 2010, 13:21
Hi Malcolm

PM sent. Just in case you don't get it, you can PM me

Regards

malc-c
- 15th September 2010, 14:41
Thanks,

Jerson, and Henrik for the PM's - I've responded via e-mail

Many thanks

malc-c
- 18th September 2010, 17:09
OK I'm at a loss - I don't know if it's the code that's the problem, the PIC, or the development board.

The corruption now appears to be limited to just the bottom line of the 4 x 20 LCD. I've noticed that it tends to over-write the clock that's down in the bottom left of the display

The normal display looks like
http://micro-heli.co.uk/lcd1.jpg

Yet sometimes at random time the clock got over-written for a split second and the sometime sets points will revert back to 00, like this, sometimes

http://micro-heli.co.uk/lcd2.jpg

This is even when running without the serial cable connected. When I've got the serial cable hooked up and the 27th Q is sent the PIC either reboots and the LCD screen looks like the one above, or it doesn't reboot but displays a scrolling garbage like

http://micro-heli.co.uk/lcd3.jpg

Thinking it might be a problem with the LCD I took the one out of my prototype controller that's been used to keep my snakes warm... this too displays the same issue when plugged into the EasyPIC5 board.

So.. I started loading the same version of HEX that has been running in the prototype for the past two months (which has the original coms DT wrote for use with Hyperterm and doesn't use the PC app Charles has produced) and that too over-wrote the clock leaving 15 after the minutes.

OK maybe the RTC module I'm using is causing the issue, possibly corrupting the values



I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCY ear,RTCCtrl] ; read DS1307 chip
If RTCHour.6=1 then

CounterA=(RTCHour>>4)&$01 ' Work-Out 12 or 24 hour Display for Hours
else
CounterA=(RTCHour>>4)&$03
endif
CounterA=CounterA*10+(RTCHour&$0F) ' Display Hours appropriately for 12 or 24 hour Mode
If RTCHour.6=1 then
LCDOut $FE,$D4,#CounterA
else
LCDOut $FE,$D4,#CounterA Dig 1,#CounterA Dig 0
endif
LCDOut ":",#(RTCMin>>4)&$0F,#RTCMin&$0F


for arguments sake it could be writing 26:6415 (which once on setting the time I found the variables used to equal such stupid numbers) and the when it goes back to displaying 16:26 the 15 is left behind - no problem, I can simply add LCDOut $FE,$D4+5," " to over-write it... BUT this doesn't explain why when I send Q to the PIC manually via the Hyperterm program, or use Charlies PC application to poll the PIC that it re-boots on the 27th Q, even when the DS1307 module has been removed.

The way I can tell it reboots is that after all the initialization, the first thing the PIC does is jump to an "about" subroutine that simply displays the current version of the code on the LCD, then jumps to the main program loop, so it has to be reset to display this screen.

Note:
I've subsequently moved the section which reads the stored values for each variable so now when it reboots the set temperatures are no longer zeroed as shown in the second image.

Jerson
- 19th September 2010, 16:47
Hi Malcolm

Can you try to just slow down the updates to LCD to say once every second? Sometimes updating the LCD too quickly can cause such behaviour

Regards
Jerson

malc-c
- 19th September 2010, 17:20
Hi Malcolm

Can you try to just slow down the updates to LCD to say once every second? Sometimes updating the LCD too quickly can cause such behaviour

Regards
Jerson

do you mean in the section


DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us


or in the section that drop the data in



ShowLCD:
LOOKUP pid_Channel,[$80,$C0,$89,$C9],Bvar ; Find location
LCDOUT $FE,Bvar,DEC1 pid_Channel+1,"= " ; print to LCD
TempWD = TempC : GOSUB TempToLCD ; display TempC
LCDOUT $DF ; deg symbol


I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCY ear,RTCCtrl] ; read DS1307 chip
If RTCHour.6=1 then

CounterA=(RTCHour>>4)&$01 ' Work-Out 12 or 24 hour Display for Hours
else
CounterA=(RTCHour>>4)&$03
endif
CounterA=CounterA*10+(RTCHour&$0F) ' Display Hours appropriately for 12 or 24 hour Mode
If RTCHour.6=1 then
LCDOut $FE,$D4,#CounterA
else
LCDOut $FE,$D4,#CounterA Dig 1,#CounterA Dig 0
endif
LCDOut ":",#(RTCMin>>4)&$0F,#RTCMin&$0F

timeH=(RTCHour>>4) 'convert the BCD format of the hours register and store in variable timeH
timeH=(timeH &$03)*10
timeH=timeH+(RTCHour&$0F)

timeM=(RTCMin>>4)
timeM=(timeM &$07)*10
timeM=timeM+(RTCMin&$0F) 'convert the BCD format of the mins register and store in variable timeM

LCDOut $FE,$D4+8,#setpoints(0)dig 2,#setpoints(0)dig 1,$FE,$D4+11,#setpoints(1)dig 2,#setpoints(1)dig 1 ' show current set temperatures
LCDOut $FE,$D4+14,#setpoints(2)dig 2,#setpoints(2)dig 1,$FE,$D4+17,#setpoints(3)dig 2,#setpoints(3)dig 1

Jerson
- 19th September 2010, 17:54
Hi Malc

I suspect the second section is going a bit fast for the lcd to keep up.

I normally slow down the updates to about twice a second to about once a second. This should iron out any timing issues with the LCD

Regards

malc-c
- 19th September 2010, 18:43
Well the stray "15" on the LCD seems to stem from the RTC as this doesn't happen when the module is un-plugged, and as I've seen it momentarily displays the wrong time, and the fact thta this happens on nearly every version of code, most of which has been fine in the past does suggest this is a hardware issue. However the PIC still reboots on the 27th Q.... Why is it always the 27th... that's what I can't figure out... and this is irrspective of what's used to communicate with the PIC

HenrikOlsson
- 24th September 2010, 18:19
Hi Malcolm,
How's it going? Have you been able to find any cause for the weired characters and lockup? It's interesting that it locks up in (what seems to be) such a repeatable manner.

/Henrik.

malc-c
- 25th September 2010, 00:14
Hi,

Regret that due to a bereavement in the family I've not had much of a chance to look at this over the past week. I would love to know why it's so repeatable, and why / how it's resetting the PIC.

Hopefully once the family matters are resolved I'll get back to this and we'll get to the bottom of this issue. I've just taken delivery of 6 PCB's I've had made in HK, and might try and occupy my self by assembling one of these next week then hook it up to see if this replicates the problem. At least this would then rule out a problem with the EasyPIC 5 board, although when I loaded up a version of the original code that used hyperterm to send the PID values this ran without issue for quiet some time. The only other thing I noticed last week, was that occasionally the RTC seemed to display totally wrong time (27:67:65 for example) so maybe the poling is screwing up the memory, or the timing of the I2C bus or something equally screwy ???

malc-c
- 26th September 2010, 13:10
Update,

I'm stumped as to why this is happening when the 27th byte is sent. To check if it was the sending of data that was the problem, I simply made the code jump to the TX part of the program and send the data, then pause a little while before returning to the main program loop. When I ran this the PIC ran fine, sending data over and over again.

So this would suggest that the trigger is something to do with the receiving side. But what ?

The code simply jumps to either the sub-routine that receives data and updates variables or the subroutine that sends data, depending if Q or S is received. What is significant about the 27th byte !

FIXED !!!!!

I have no idea if this is just murphy's law or it was something to do with the mix of gosubs / goto's but I've re-coded as follows and it seems to work (well it's sent over 35 bytes to the PIC and it hasn't yet restarted)



;----[check for data on com port]

FOR TempWD = 0 TO 10000
IF RCIF THEN GOTO coms
PauseUs 100
NEXT TempWD
;--------------------------------



I then have the checking for Q or S



coms:
HSERIN [nTest]
SELECT CASE nTest
CASE "Q" ; if Q then send data to PC
Goto Term_TX
CASE "S"
goto Term_RX
return


Then the TX and RX simply jump back to the start of the main loop after sending or receiving data

Why placing the test for Q or S inside the RX bit caused the problem, when segregating it as a separate sub routine I have no idea... and I seem to recall I tried this the other week.... but guess I got lucky this time round :)