serial coms - again


Closed Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 58
  1. #1
    malc-c's Avatar
    malc-c Guest

    Default serial coms - again

    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
    Code:
    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

    Code:
    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 )

  2. #2
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    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.
    Last edited by Bruce; - 20th August 2010 at 17:42.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  3. #3
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    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?

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    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.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    cheers Bruce...

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

  6. #6
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Bruce,

    One other thing that has come to light is that I need clear the buffer after
    Code:
    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

  7. #7
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    I'm not 100% sure what you're asking Malc?
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  8. #8
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    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.

  9. #9
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default VB Express 2008

    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
    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.SerialPortNames(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.



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

    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.

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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.

  11. #11
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    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

  12. #12
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default formatting data sent to port

    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 ?

  13. #13
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    Hi,
    If you HSEROUT DEC3 Temperatures(0) it will write three digits, ie. 000 if the value is 0.

    /Henrik.

  14. #14
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Thankyou - works a treat

  15. #15
    Join Date
    Aug 2008
    Location
    Portugal
    Posts
    240


    Did you find this post helpful? Yes | No

    Default

    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;
    Code:
     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.

  16. #16
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    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
    Code:
    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]]
    Last edited by malc-c; - 22nd August 2010 at 10:38. Reason: forgot to ask about the pbp side

  17. #17
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default Serial in

    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



    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

    Code:
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     
        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

    Code:
    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

    Code:
    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.
    Attached Images Attached Images  

  18. #18
    Join Date
    Feb 2010
    Location
    USA, New England
    Posts
    164


    Did you find this post helpful? Yes | No

    Default

    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

    Code:
    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

  19. #19
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Paul,

    Many thanks for the prompt reply.

    One further question, in the original code there was the command to WRITE the result
    Code:
    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
    Code:
    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 ?

  20. #20
    Join Date
    Feb 2010
    Location
    USA, New England
    Posts
    164


    Did you find this post helpful? Yes | No

    Default

    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

  21. #21
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    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.

    Code:
    ;----[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

  22. #22
    Join Date
    Feb 2010
    Location
    USA, New England
    Posts
    164


    Did you find this post helpful? Yes | No

    Default

    Hi Malcom,

    Try changing the end of your code to this:
    Code:
    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

  23. #23
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default Banging head against wall !

    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.

    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
    
    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.



    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



    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.



    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.

  24. #24
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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?
    Last edited by HenrikOlsson; - 28th August 2010 at 17:41.

  25. #25
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    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

    Code:
    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 ?
    Last edited by malc-c; - 28th August 2010 at 19:41.

  26. #26
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    Hi,
    I just tried a somewhat modifed version here (to be able to test on my hardware).
    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
     
    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.
    Attached Images Attached Images  

  27. #27
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post

    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.

  28. #28
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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:
    Code:
    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.

  29. #29
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Well I have no idea what's happening. I added the sub routine at the end of the code and then called it thus
    Code:
    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
    Code:
    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

  30. #30
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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.

  31. #31
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Thumbs up Now we're getting somewhere

    Full Code:

    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

    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 ?

  32. #32
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Uhmmm strange things.. I spoke too soon.

    If I follow your example code
    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 )

  33. #33
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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:
    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.

  34. #34
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    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 ?

  35. #35
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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:
    Code:
    WaitHere:
    For I = 0 to 10000
      If RCIF = 1 then GOSUB Term_Rx
      PauseUs 100
    Next
    Keep it up!
    /Henrik.

  36. #36
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    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
    Code:
    FOR TempWD = 0 TO 1000
    to
    Code:
    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

    Code:
    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

    Code:
    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 ?

  37. #37
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    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:
    Code:
    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....

    Code:
    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.

  38. #38
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Ok I see the logic behind the pause statement.

    I've managed to resolve the stalling...

    Code:
     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 !

  39. #39
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default Incoming !!

    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

    QS350635250249250250250249250250250249000000000000000000000000000000001501501501500000000000000000Q

    This should then populate the variables as follows

    Code:
    [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

    Code:
       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 ?
    Last edited by malc-c; - 30th August 2010 at 16:49. Reason: more info on the error

  40. #40
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Any reason why
    Code:
    hserout [#StartHour[0] DIG 1,#StartHour[0] DIG 0,#StartMin[0] DIG 1,#StartMin[0] DIG 0]
    compiles, but
    Code:
    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

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts