Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

12F675 with RF315 module

Status
Not open for further replies.

mastero

Member
Hello all,


I am trying to use RF module with PIC12f675.

My code till now.

TX CODE:
********************************************************************
Dim i As Byte

CMCON = 7

TRISIO = %00001111

Symbol led = GPIO.5
loop:
led = 0
If GPIO.3 = 0 Then
Serout GPIO.4, 9600, "1", CrLf
Toggle led
Endif

If GPIO.0 = 0 Then
Serout GPIO.4, 9600, "2", CrLf
Toggle led
Endif

If GPIO.1 = 0 Then
Serout GPIO.4, 9600, "3", CrLf
Toggle led
Endif
If GPIO.2 = 0 Then
Serout GPIO.4, 9600, "4", CrLf
Toggle led
Endif
Goto loop
*********************************************************
RX CODE:
*********************************************************
Dim i As Byte
Symbol led = GPIO.0

CMCON = 7
TRISIO = %00100000
GPIO.1 = 0
GPIO.2 = 0

loop:
led = 0
Serin GPIO.5, 9600, i
If i > 0 Then
Gosub check
Else
Gosub loop
Endif

check:
If i = "1" Then
GPIO.1 = 1
Toggle led
Else

If i = "2" Then
GPIO.1 = 0
Toggle led
Else

If i = "3" Then
GPIO.2 = 1
Toggle led
Else

If i = "4" Then
GPIO.2 = 0
Toggle led
Endif
Endif
Endif
Endif
Gosub loop
End
************************************************************************

This code works perfect....

Instead of one digit i want to send say ten digit at the press of a button.

how to ?? any idea shall be good

Thanx in advance.

Mastero
 
Not sure what you are going to do with 10 digits if all you can decode on the RX is 4 states. Regardless, if you want to send more than one digit, simply make the string longer, or concatenate the data like:
Serout GPIO.4, 9600, "1","2","3", CrLf

On the receive side, you would have to read all characters and re-assemble them into the format you want, and look for the "Cr" or Lf" as a read terminator. You would have to loop on a single character read until you hit that Cr character, read the LF and dump it, then build your read string.

Another option would be to encode a byte as a hex value, anywhere from 0 to 255 (0x255), and process that as a result on a single character read.

Also, look into using the read interrupt bit for the software uart, as to not get hung on a read that does not come. You can also use an un-used GPIO input pin as a read interrupt signal.
Finally, use the "AllDigital" at the start of the code, easier than setting CMCON and ANSEL ( you are missing ANSEL = 0 in your code) if your code is all digital states.
 
Still no luck

What am i doing wrong?

TX-CODE

C:
Define CONF_WORD = 0x3194
Define CLOCK_FREQUENCY = 4
'Define SIMULATION_WAITMS_VALUE = 1

AllDigital
TRISIO = %00000000

Dim i As Byte
Dim datatimer As Byte
Dim delaycount As Byte

Symbol led = GPIO.2
Symbol vdd = GPIO.1

i = 0
led = 1
vdd = 0
datatimer = 200
delaycount = 200

'****************************************************
WaitMs 1000
led = 0

ASM:        bsf STATUS,RP0 ;bank 1
ASM:        call 3ffh ;get the cal value
ASM:        movwf OSCCAL ;calibrate
ASM:        bcf STATUS,RP0 ;bank 0
ASM:

main:

Gosub decrement_counters
Gosub senddata

Goto main
End                                              

'****************************************************

decrement_counters:
    If delaycount = 0 Then


        If datatimer > 0 Then
            datatimer = datatimer - 1
        Endif

        delaycount = 200
    Else
        delaycount = delaycount - 1
    Endif
Return                                            

'****************************************************
senddata:

If datatimer = 0 Then
    vdd = 1
    led = 1
    Serout GPIO.0, 9600, "+", "A", "B", "C", "D", "E", "#", CrLf
    vdd = 0
    WaitMs 50
    led = 0

    datatimer = 200
Endif

Return

RX-CODE:

C:
Define CONF_WORD = 0x3194
Define CLOCK_FREQUENCY = 4

'Define SIMULATION_WAITMS_VALUE = 1

AllDigital
TRISIO = %00000001

Dim i As Long
Dim k As Byte
Dim j As Byte
Dim data(20) As Byte
Dim serdata As Byte
Dim allok As Bit
Dim startmark As Bit
Dim temp As Byte

Symbol led = GPIO.2
Symbol relay = GPIO.1

j = 0
i = 0
k = 0
led = 1
relay = 1
allok = False
startmark = False

WaitMs 1000

relay = 0
led = 0

For k = 0 To 20 Step 1  'clear buffer
        data(k) = 0x00
Next k

ASM:        bsf STATUS,RP0 ;bank 1
ASM:        call 3ffh ;get the cal value
ASM:        movwf OSCCAL ;calibrate
ASM:        bcf STATUS,RP0 ;bank 0

main:

    Gosub loop
    Gosub dodata

Goto main
    End

loop:
j = 0
i = 0
k = 0
startmark = False
allok = False

loop_nr:
            Serin GPIO.0, 9600, serdata
                If serdata > 0 Then

                    If serdata = "+" Then
                        startmark = True
                    Endif

                    If serdata = "#" And startmark = True Then
                        startmark = False
                        allok = True
                    Endif

                    If startmark = True Then
                        data(j) = serdata  'store data in buffer
                        If j = 20 Then
                            j = 0
                        Else
                            j = j + 1
                        Endif
                        Goto loop_nr
                    Endif

        Endif
    Return

dodata:

If allok = True Then
If data(1) = "A" Then
If data(2) = "B" Then
If data(3) = "C" Then
If data(4) = "D" Then
If data(5) = "E" Then


relay = 1
WaitMs 10000
relay = 0
allok = False

For k = 0 To 20 Step 1  'clear buffer
        data(k) = 0x00
Next k


Endif
Endif
Endif
Endif
Endif
Endif
    Return


Help me please someone :(
 
Last edited:
First, do the ASM code after the start of the program (after i=0, led=1). It needs to be only done before the main "loop". Second, a RX program will not see those " marks, those denote Ascii characters to send in the sending routine. The RX routine should just be looking for the + sign first, then the A, then the B, and so on.
Your "Lookup" function seems pointless, just check if serdata = "+" (or start trigger), then trigger the loop to read the rest.
Waiting 100Ms between characters will miss the next character after the "startmark" is set...

Back up a bit here. Simply do a RX read loop looking for the start, store the characters received until the CR or LF is received (accounting for overflow - then error). Only then, start to process the entire buffer in a separate loop to parse if the buffer is correct. You could even double the buffer size to account for out-of-sync messages, just look for the first + (or start) character as start of message.

PS: I have not looked at the continuity of the code itself, but running this in the simulator should show any logic bugs.
 
Last edited:
I tested the RX code in the simulator, works as it should, but:
1) You should clear the buffer/received array after toggling the LED pin
2) You code is missing the config definitions. I used (internal OSC, everything else cleared):
Define CONFIG = 0x3194
3) You do not need the CMCON if you use "AllDigital", it sets it.

I send the string "+ABCDE# in the software terminal emulator (define GPIO.0 as input), one byte at a time. You code seems to work (does not save the last "#", but not relevant).
Code for RX: (I have to comment out the ASM code in suimulator as simulator reads invalid data). Un-comment the ASM code for real compile.

Will look at TX code when I have time...




Define CONFIG = 0x3194

AllDigital
TRISIO = %00000001

'Define SIMULATION_WAITMS_VALUE = 1

Dim i As Long
Dim k As Byte
Dim j As Byte
Dim data(20) As Byte
Dim serdata As Byte
Dim allok As Bit
Dim startmark As Bit
Dim temp As Byte

Symbol led = GPIO.2
Symbol relay = GPIO.1

j = 0
i = 0
k = 0
led = 1
relay = 1
allok = False
startmark = False

WaitMs 1000

relay = 0
led = 0

'ASM: bsf STATUS,RP0 ;bank 1
'ASM: call 3ffh ;get the cal value
'ASM: movwf OSCCAL ;calibrate
'ASM: bcf STATUS,RP0 ;bank 0

main:

Gosub loop
Gosub dodata

Goto main
End

loop:
j = 0
i = 0
k = 0
startmark = False
allok = False

loop_nr:
Serin GPIO.0, 9600, serdata

If serdata > 0 Then

If serdata = "+" Then
startmark = True
Endif

If serdata = "#" And startmark = True Then
startmark = False
allok = True
Endif

If startmark = True Then
data(j) = serdata 'store data in buffer
If j = 20 Then
j = 0
Else
j = j + 1
Endif
Goto loop_nr
Endif

Endif
Return

dodata:
If allok = True Then
If data(1) = "A" Then
If data(2) = "B" Then
If data(3) = "C" Then
If data(4) = "D" Then
If data(5) = "E" Then

relay = 1
WaitMs 10000
relay = 0
allok = False

Endif
Endif
Endif
Endif
Endif
Endif
Return
 
Checked the TX code, it does what it is supposed to. No need for the CrLf at the end, as that just adds more garbage characters that are not needed by the RX code anyway. Again, make sure you define the config flags, define the Mhz as well (I missed that in the RX code as well - make sure you define the frequency so the compiler knows how to do the serial timings!)
Your datatimer and delaycount add up to almost 1 second total (I make it about 0.8 to 0.88 seconds)
Enable the ASM: code as well...

Code:
Define CONFIG = 0x3194

'Define SIMULATION_WAITMS_VALUE = 1
Define CLOCK_FREQUENCY = 4.0


AllDigital
TRISIO = %00000000
Dim i As Byte
Dim datatimer As Byte
Dim delaycount As Byte
Symbol led = GPIO.2
Symbol vdd = GPIO.1

i = 0
led = 1
vdd = 0
datatimer = 200
delaycount = 200

'****************************************************
WaitMs 1000
led = 0

'ASM: bsf STATUS,RP0 ;bank 1
'ASM: call 3ffh ;get the cal value
'ASM: movwf OSCCAL ;calibrate
'ASM: bcf STATUS,RP0 ;bank 0
'ASM:
main:

Gosub decrement_counters
Gosub senddata

Goto main
End

'****************************************************

decrement_counters:
If delaycount = 0 Then


If datatimer > 0 Then
datatimer = datatimer - 1
Endif

delaycount = 200
Else
delaycount = delaycount - 1
Endif
Return

'****************************************************
senddata:

If datatimer = 0 Then
vdd = 1
led = 1

Serout GPIO.0, 9600, "+", "A", "B", "C", "D", "E", "#", CrLf
vdd = 0
WaitMs 50
led = 0

datatimer = 200
Endif

Return
 
Like I said, the code works in the simulator as I posted it. I notice there are longer delays in the RX code (delay 10S) vs the TX code which sends about every second or so. The RX code will not get characters until it has finished its timings, and goes back to read again.
Also, have you checked the calibration factor in the 12F675 chips? A full erasure will remove the proper values, and clock speeds will vary a lot, enough to cause errors in serial data rates. Also, if fully erased, including the OSCCAL value, the code may crash and simply repeat from start. One must ensure the OSCCAL value is there. For example, one of my 675 chips has an OSCCAL of 3420 hex. OSCCAL is located at address 0x3FF (last byte of program ram). A PicKit2 (or 3) has a tool that can automatically regenerate the proper OSCCAL value and write it to that location.

Another debugging method is to put in a few more LED flashes though the code (in non-critical areas). So, one flash is start of code, two flashes is start of uart send, etc. I would put in an error indicator in RX if J hits 20, you should really exit at that point as the data is too scrambled. Do a several LED flash in that case and exit.

Now, how are the TX and RX connected to each other? If using a wire to test, that is the best option to make sure the communications is correct. Make sure you have a pull-up resistor on that TX/RX line (about 10k will do), and same ground between the PICs. Only once the comm is working can you look at other means to connect the two PICs for communications.

You have an error in zeroing the data array. An array of 20 starts at 0, ends at 19, not 20. Your zero loops should read 0 to 19. That also means you cannot check for 20 in the read loop, since you cannot store a value in data(20), it does not exist

Otherwise I see no reason why the code should not work. You can try lowering the speeds to 1200baud or something like that to reduce the amount of error if it is timing related.
 
The connection is via 315mhz Rf modules.

One character works fine but when I send multiple character there is an issue and it does not read well.

Very frustrating
 
Radio links often require lots of delay. Try setting the character delay for SEROUT with the command:
SEROUT_DELAYUS
Default is 1000uS (1mS). Maybe increase that by 10 or 20. All that setting does is provide a delay between each sent character when sending a string of them.
Or, send one character at a time, and put in a "Waitms 5000" or bigger between each character (use a send array that is coded with all characters, and do a "FOR" loop for sending one character and add delay after each)

As for the RF module, does it have any "status" bits/signals, to indicate "ready" or link is "connected and good" ?

Many of those RF link modules pick up lots of noise, invalid characters. There is no checksums or character validation with those. Some have a maximum data rate of 2400 or 4800, not 9600. Getting zeros is an indication of no signal, or no data. Maybe loop in loop_nr reading zeros and dumping them until you see a "+" and only then start grabbing data. I suspect your RX code has to process all characters, even zeroes, and determine what to do and when (needs a bit more logic)
Typical RF link unit:
https://www.sparkfun.com/datasheets/RF/KLP_Walkthrough.pdf

PS: Also try inverting the signals for serial on both ends. Use SEROUTINV and SERININV as suggested by this article (different basic compiler)
https://digitaldiy.io/articles/mcu-...n-basic-example/90-proton-tutorial-rf-modules
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top