Menu

soft serial not returning

Help
Chris
2012-04-22
2013-05-30
  • Chris

    Chris - 2012-04-22

    im having trouble with software serial receive. i have serial from a pc running into a pic through the pics ext int pin. i receive the characters just fine, but sometimes, randomly it doesnt exit my serial interrupt sub (i have the ext int set up to go into a sub that only received the byte from the serial, and repeats it back out to the pc, itll receive the byte, retransmit it, but it doesnt exit the sub to take the action based on what the byte was, but it usually (but not always) will still retrasmit the character, but randomly will stop exiting the interrupt sub and take the action). ive tryed using IntOff at the begining of the interrupt sub, and IntOn at the end of the sub, i still get a random crash after a while of receiving charecters. i took the interrupt sub out and so far have no crash. oh and i have another interrupt for timer0 for my IR remote decodeing section of my program. is this a problem with GCbasic or is there something im missing?

    ;Chip Settings
    #chip 16F616,8
    #config MCLRE=OFF, WDT=OFF
    ;Defines (Constants)
    #define button_on porta.3=0
    #define button_off porta.3=1
    #define led1 portc.3
    #define output1 portc.4
    #define SendAHigh porta.1= on
    #define SendALow porta.1 = off
    #define RecAHigh porta.2 on
    #define RecALow porta.2 off
    #define PWM_Freq 40
    #define PWM_Duty 100
    #define led2 portc.5
    #define remote_in porta.0
    #define relay_out portc.0
    ;Variables
    Dim power_out As bit
    Dim temp As byte
    Dim light_sensor As byte
    Dim sensor(2)
    Dim sensor_counter As byte
    Dim brightness As byte
    Dim nightlight_var As bit
    Dim print_out As bit
    Dim toggle As bit
    Dim counter As byte
    Dim delay_temp As byte
    Dim timeout As bit
    Dim start_byte As byte
    Dim code_word As word
    Dim hold_counter As byte
    Dim button_held As bit
    Dim serial_send As bit
    Dim toggle_power As bit
    ;Interrupt Handlers
    On Interrupt ExtInt0 Call serial_receive
    On Interrupt Timer0Overflow Call timer0_overflow
    'x power
    'xxx sesor1
    'xxx sesor2
    'xxx brightness
    'x nightlight_var
    'xxxx remote
    Set relay_out Off
    Dir portc.5 Out
    Set NOT_RAPU Off
    Set WPUA.0 On
    InitSer 1, r4800, 1+WaitForStart, 8, 1, None, Invert
    InitTimer0 Osc, PS0_1/32
    brightness = 200
    Do Forever
        If button_on Then
            toggle_power = 1
            Wait 250 ms
        End If
        If toggle_power=1 Then
            toggle_power = 0
            If power_out=0 Then
                nightlight_var = 0
                power_out = 1
                Goto skip_off
            End If
            power_out = 0
            skip_off:
            serial_send = 1
        End If
        If power_out=0 Then
            Set output1 Off
            Set led1 Off
        End If
        If power_out=1 Then
            Set output1 On
            Set led1 On
        End If
        If sensor(1)<1 and power_out=0 Then
            If toggle=0 Then
                toggle = 1
                nightlight_var = 1
            End If
        End If
        If sensor(1)>15 or power_out=1 Then
            If toggle=1 Then
                toggle = 0
                nightlight_var = 0
            End If
        End If
        If nightlight_var=0 Then
            HPWM 1, 40, 0
        End If
        If nightlight_var=1 Then
            HPWM 1, 40, brightness
        End If
        If remote_in=0 Then
            remote_receive
        End If
        sensor(1) = readAD(an6)
        sensor(2) = readAD(an5)
        hold_counter = hold_counter+1
        If hold_counter>=255 Then
            hold_counter = 0
            Set relay_out Off
        End If
        If serial_send=1 Then
            serial_send = 0
            SerPrint 1, power_out
            sensor_counter = 0
            Do Until sensor_counter=>2
                sensor_counter = sensor_counter+1
                If sensor(sensor_counter)<100 Then
                    SerPrint 1, "0"
                End If
                If sensor(sensor_counter)<10 Then
                    SerPrint 1, "0"
                End If
                SerPrint 1, sensor(sensor_counter)
            Loop
            If brightness<100 Then
                SerPrint 1, "0"
            End If
            If brightness<10 Then
                SerPrint 1, "0"
            End If
            SerPrint 1, brightness
            SerPrint 1, nightlight_var
            If code_word<1000 Then
                SerPrint 1, "0"
            End If
            If code_word<100 Then
                SerPrint 1, "0"
            End If
            If code_word<10 Then
                SerPrint 1, "0"
            End If
            SerPrint 1, code_word
            code_word = 1111
        End If
    Loop
    Sub serial_receive
        IntOff
        SerReceive 1, temp
        IntOff
        If temp=43 Then
            '+
            nightlight_var = 1
        End If
        If temp=45 Then
            '-
            nightlight_var = 0
        End If
        If temp=48 or temp=49 Then
            '0 or 1
            power_out = temp-48
        End If
        If temp=>97 and temp<=122 Then
            'a to z
            brightness = (temp-97)*10
        End If
        temp = 0
        serial_send = 1
        IntOn
    End Sub
    Sub remote_receive
        If power_out=1 Then
            Set led1 Off
        End If
        If power_out=0 Then
            Set led1 On
        End If
        hold_counter = 0
        code_word = 0
        start_byte = 0
        counter = 0
        ClearTimer 0
        timeout = 0
        Do Until counter=>22
            counter = counter+1
            ClearTimer 0
            If remote_in=0 Then
                Wait Until remote_in=1 or timeout=1
                Goto skip_wait_zero
            End If
            Wait Until remote_in=0 or timeout=1
            skip_wait_zero:
            delay_temp = Timer0
            If remote_in=0 Then
                delay_temp = delay_temp+10
            End If
            If timeout=1 Then
                delay_temp = 33
            End If
            If counter<=8 Then
                Rotate start_byte Left
                If delay_temp<90 Then
                    start_byte.0 = 0
                End If
                If delay_temp>90 Then
                    start_byte.0 = 1
                End If
            End If
            If counter>12 Then
                Rotate code_word Left
                If delay_temp<90 Then
                    code_word.0 = 0
                End If
                If delay_temp>90 Then
                    code_word.0 = 1
                End If
            End If
        Loop
        If start_byte=9 or start_byte=33 Then
            Goto code_accept
        End If
        Wait 20 ms
        Goto remote_end
        code_accept:
        If code_word=9 Then
            'power
            Set relay_out On
        End If
        If code_word=512 Then
            'mute
            toggle_power = 1
            Wait 114 ms
            Goto remote_end
        End If
        If code_word=530 Then
            'CHUP
            nightlight_var = 1
            If brightness<250 Then
                brightness = brightness+10
                Wait 150 ms
            End If
        End If
        If code_word=584 Then
            'CHDN
            nightlight_var = 1
            If brightness>0 Then
                brightness = brightness-10
                Wait 150 ms
            End If
        End If
        serial_send = 1
        remote_end:
        Wait 80 ms
    End Sub
    Sub timer0_overflow
        timeout = 1
    End Sub
    
     
  • Chris

    Chris - 2012-04-22

    ignore the previous code, when the interrupt wouldnt exit, with that code it wouldnt retransmit the info. with this code itll retransmit the info, and change the variables but will not exit to make the variables take action

    by the way, it would be nice to have a remote control decode library but ive managed to make a decode routine for my remote (which uses a highly non standard set of pulses) which times the length of the high, and low pulses and turns long pulses into 1's and short ones into 0's. for my remote the first 12 bits are start bits, and device id (i guess) and the rest is the button code (though the amount of pulses arent constant, hence the need for the timer overflow to prevent and endless wait for a bit that isnt going to arrive)

    ;Chip Settings
    #chip 16F616,8
    #config MCLRE=OFF, WDT=OFF
    ;Defines (Constants)
    #define button_on porta.3=0
    #define button_off porta.3=1
    #define led1 portc.3
    #define output1 portc.4
    #define SendAHigh porta.1= on
    #define SendALow porta.1 = off
    #define RecAHigh porta.2 on
    #define RecALow porta.2 off
    #define PWM_Freq 40
    #define PWM_Duty 100
    #define led2 portc.5
    #define remote_in porta.0
    #define relay_out portc.0
    ;Variables
    Dim power_out As bit
    Dim temp As byte
    Dim light_sensor As byte
    Dim sensor(2)
    Dim sensor_counter As byte
    Dim brightness As byte
    Dim nightlight_var As bit
    Dim print_out As bit
    Dim toggle As bit
    Dim counter As byte
    Dim delay_temp As byte
    Dim timeout As bit
    Dim start_byte As byte
    Dim code_word As word
    Dim hold_counter As byte
    Dim button_held As bit
    Dim toggle_power As bit
    ;Interrupt Handlers
    On Interrupt ExtInt0 Call serial_receive
    On Interrupt Timer0Overflow Call timer0_overflow
    'x power
    'xxx sesor1
    'xxx sesor2
    'xxx brightness
    'x nightlight_var
    'xxxx remote
    Set relay_out Off
    Dir portc.5 Out
    Set NOT_RAPU Off
    Set WPUA.0 On
    InitSer 1, r4800, 1+WaitForStart, 8, 1, None, Invert
    InitTimer0 Osc, PS0_1/32
    brightness = 200
    Do Forever
        If button_on Then
            toggle_power = 1
            Wait 250 ms
        End If
        If toggle_power=1 Then
            toggle_power = 0
            If power_out=0 Then
                nightlight_var = 0
                power_out = 1
                Goto skip_off
            End If
            power_out = 0
            skip_off:
            send_info
        End If
        If power_out=0 Then
            Set output1 Off
            Set led1 Off
        End If
        If power_out=1 Then
            Set output1 On
            Set led1 On
        End If
        If sensor(1)<1 and power_out=0 Then
            If toggle=0 Then
                toggle = 1
                nightlight_var = 1
            End If
        End If
        If sensor(1)>15 or power_out=1 Then
            If toggle=1 Then
                toggle = 0
                nightlight_var = 0
            End If
        End If
        If nightlight_var=0 Then
            HPWM 1, 40, 0
        End If
        If nightlight_var=1 Then
            HPWM 1, 40, brightness
        End If
        If remote_in=0 Then
            remote_receive
        End If
        sensor(1) = readAD(an6)
        sensor(2) = readAD(an5)
        hold_counter = hold_counter+1
        If hold_counter>=255 Then
            hold_counter = 0
            Set relay_out Off
        End If
    Loop
    Sub serial_receive
        IntOff
        SerReceive 1, temp
        IntOff
        If temp=43 Then
            '+
            nightlight_var = 1
        End If
        If temp=45 Then
            '-
            nightlight_var = 0
        End If
        If temp=48 or temp=49 Then
            '0 or 1
            power_out = temp-48
        End If
        If temp=>97 and temp<=122 Then
            'a to z
            brightness = (temp-97)*10
        End If
        temp = 0
        send_info
        IntOn
    End Sub
    Sub remote_receive
        If power_out=1 Then
            Set led1 Off
        End If
        If power_out=0 Then
            Set led1 On
        End If
        hold_counter = 0
        code_word = 0
        start_byte = 0
        counter = 0
        ClearTimer 0
        timeout = 0
        Do Until counter=>22
            counter = counter+1
            ClearTimer 0
            If remote_in=0 Then
                Wait Until remote_in=1 or timeout=1
                Goto skip_wait_zero
            End If
            Wait Until remote_in=0 or timeout=1
            skip_wait_zero:
            delay_temp = Timer0
            If remote_in=0 Then
                delay_temp = delay_temp+10
            End If
            If timeout=1 Then
                delay_temp = 33
            End If
            If counter<=8 Then
                Rotate start_byte Left
                If delay_temp<90 Then
                    start_byte.0 = 0
                End If
                If delay_temp>90 Then
                    start_byte.0 = 1
                End If
            End If
            If counter>12 Then
                Rotate code_word Left
                If delay_temp<90 Then
                    code_word.0 = 0
                End If
                If delay_temp>90 Then
                    code_word.0 = 1
                End If
            End If
        Loop
        If start_byte=9 or start_byte=33 Then
            Goto code_accept
        End If
        Wait 20 ms
        Goto remote_end
        code_accept:
        If code_word=9 Then
            'power
            Set relay_out On
        End If
        If code_word=512 Then
            'mute
            toggle_power = 1
            Wait 114 ms
            Goto remote_end
        End If
        If code_word=530 Then
            'CHUP
            nightlight_var = 1
            If brightness<250 Then
                brightness = brightness+10
                Wait 150 ms
            End If
        End If
        If code_word=584 Then
            'CHDN
            nightlight_var = 1
            If brightness>0 Then
                brightness = brightness-10
                Wait 150 ms
            End If
        End If
        send_info
        remote_end:
        Wait 80 ms
    End Sub
    Sub timer0_overflow
        timeout = 1
    End Sub
    Sub send_info
        SerPrint 1, power_out
        sensor_counter = 0
        Do Until sensor_counter=>2
            sensor_counter = sensor_counter+1
            If sensor(sensor_counter)<100 Then
                SerPrint 1, "0"
            End If
            If sensor(sensor_counter)<10 Then
                SerPrint 1, "0"
            End If
            SerPrint 1, sensor(sensor_counter)
        Loop
        If brightness<100 Then
            SerPrint 1, "0"
        End If
        If brightness<10 Then
            SerPrint 1, "0"
        End If
        SerPrint 1, brightness
        SerPrint 1, nightlight_var
        If code_word<1000 Then
            SerPrint 1, "0"
        End If
        If code_word<100 Then
            SerPrint 1, "0"
        End If
        If code_word<10 Then
            SerPrint 1, "0"
        End If
        SerPrint 1, code_word
        code_word = 1111
    End Sub
    
     
  • Chris

    Chris - 2012-04-23

    ok ive narrowed down the problem. the serial interrupt isnt playing nicely with the ADC. without the "readAD(an…)" in the code, it never hangs, but as soon as i put that in there, and repeatedly send a key through the serial of my pic, itll eventually hang. ive slimmed down the code to just the amount that duplicates the problem. the hardware is like this.. the "led1" pin is hooked to an leds + side, and turns ON when a 1 is written to it. when i run this code, the code hangs with the led OFF, which leads me to believe that the code is going back to the main loop where the "set led1 off" is to shut off the led. im at a loss here, i need the ADC and i would like to be able to receive (reliably without haveing to use the WDT) through the serial. any help on this one?

     
  • Chris

    Chris - 2012-04-23

    oops, forgot to post the code with my last reply, here it is..

    ;Chip Settings
    #chip 16F616,8
    #config MCLRE=OFF, WDT=OFF
    ;Defines (Constants)
    #define led1 portc.3
    #define SendAHigh porta.1= on
    #define SendALow porta.1 = off
    #define RecAHigh porta.2 on
    #define RecALow porta.2 off
    ;Variables
    Dim temp As byte
    Dim sensor(2)
    ;Interrupt Handlers
    On Interrupt ExtInt0 Call serial_receive
    InitSer 1, r4800, 1+WaitForStart, 8, 1, None, Invert
    Do Forever
        sensor(1) = readAD(an6)
        sensor(2) = readAD(an5)
        Set led1 Off
    Loop
    Sub serial_receive
        SerReceive 1, temp
        Set led1 On
        SerSend 1, temp
    End Sub
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.