[picbasic]433MHz modules foutcorrectie

Beste allemaal,

Ik ben wat aan het klooien gegaan met zend en ontvangmodukes van niels. Maar ik krijg de data heel vaak niet door. Heeft iemand een idee hoe ik foutcorrectie in picbasic kan doen? De data wordt nu met 1200 baud verstuurt. De afstand is ongeveer 10 cm. Het bleek veel te schelen als ik voorafgaand aan de data een puls van 4ms stuur en dan 4ms wacht.
huidige status:
Code:
zender

pic basic code:


Device 16F648A                ;We gebruiken een 16F628A type
Config INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal
Dim teller As Byte
TRISA = 0

main:

For teller = 0 To 100
PORTA.1 = 1
DelayMS 4
PORTA.1 = 0
DelayMS 4
SerOut PORTA.1,17197, ["Abc", teller]
Toggle PORTA.3
teller = teller + 1
DelayMS  500
Next teller
GoTo main

End

ontvanger:

pic basic code:


Device 16F648A                ;We gebruiken een 16F628A type
Config INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal
TRISA = 0
Dim inbyte As Byte

main:

SerIn PORTA.1,17197,[Wait ("Abc"),inbyte] 
Toggle PORTA.3
'stuur het door naar computer 
'zo kan je kijken wat er precies word verzonden 

SerOut PORTA.2,84, [Dec inbyte]


GoTo main

Ik krijg nu in een serie van 0 tot 100 dit binnen"

code:


612242830324042444860646668708486889094

Dus in 20% van de gevallen komt de data over.
http://www.uploadarchief.net/files/download/logicplaatje.png
Boven is in, onder is uit. Hier lijkt het dus goed te gaan, kan helaas niet goed nagaan of dit een juiste of een foutieve overdracht betrof.

Wie heeft er een idee/programma om in picbasic iets met foutcorrectie te doen.

Arco

Special Member

Als je een puls (of een serie 0xFF karakters) stuurt, is 4mS wel heel erg kort. (is nog geen half karakter op 1200 baud) Mag gerust veel langer.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Arco

Special Member

Gooi om te beginnen die interne oscillator eruit en gebruik een fatsoenlijk kristal.
Als je toch de interne oscillator wilt gebruiken, moet je ze in ieder geval ijken zodat ze beide op dezelfde frequentie draaien...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Zender alvorens de echte data komt op warmen, zend willekeurig wat ene en nullen door en daarna de echte data. Of zend de data een paar keer.

het maakt toch niet uit als de één op 4MHz draait en de ander op 20? Ik krijg als het goed is morgen mn tweede breadboardje terug die ik had uitgeleend aan een klasgenoot, dus dan kan ik testen met wat meer afstand ertussen.

Lucky Luke

Golden Member

Ik heb zoiets eens in SYP gegooid... Maar zonder code vrees ik...

Mail me maar even. Hamming(7,4) en manchester encoding, na elkaar. Decoding kan natuurlijk ook op een PIC. Zware overkill idd, en code is nog niet helemaal af. Maar het werkt wel.

Eluke.nl | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)

Op 22 september 2009 21:01:21 schreef pientertje:
het maakt toch niet uit als de één op 4MHz draait en de ander op 20? Ik krijg als het goed is morgen mn tweede breadboardje terug die ik had uitgeleend aan een klasgenoot, dus dan kan ik testen met wat meer afstand ertussen.

Het maakt misschien niet uit of de 1 op 4 MHz draait en de ander op 20MHz (dat weet ik eerlijk gezegd niet, of dat kan. Ik denk het wel).

Het maakt wel uit als ze allebei denken dat ze op 4 MHz draaien, en de 1 draait op 3,95 en de ander op 4,2 MHz. (Ik weet niet of dit reële afwijkingen zijn, maar ik weet wel dat de interne oscillatoren een flink grotere afwijking hebben als een fatsoenlijk kristal).

@lucky luke
Is dan in picbasic?

ok dan begrijp ik het. De compilert maakt de timings gelijk.

Zoals Hagdos schrijft, wél op een kristal laten draaien en niet op de interne oscillator omdat deze te veel kan afwijken.
Zelfs voor communicatie mét draad moet je de interne kristal niet gebruiken.

Ohm sweet Ohm | www.picbasic.nl

heb een kristal toegevoegd. Dit helpt iets maar nog niet genoeg. Ik heb mn mini breadboadje terug. De afstand lijkt niet of nauwlijks invloed te hebben. Heb even nieuw programmatje gemaakt:

zend

pic basic code:


Device 16F648A                ;Gebruik een 16F648A type
Config WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF, HS_OSC ;INTRC_OSC_NOCLKOUT verwijderd 
ALL_DIGITAL TRUE              ;Alle ingangen digitaal
XTAL 20                       ;Kristal van 20MHz
Dim teller As Byte
TRISA = 1


While 1 = 1
teller = 0
PORTA.3 = 0

If PORTA.0 = 1 Then 
teller = 1
PORTA.3 = 1
End If

PORTA.1 = 1
DelayMS 50

SerOut PORTA.1,17197, ["Abc", teller]

Wend


End

ontvang

pic basic code:


Device 16F648A                ;Gebruik een 16F648A type
Config WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF, HS_OSC ;INTRC_OSC_NOCLKOUT verwijderd 
ALL_DIGITAL TRUE              ;Alle ingangen digitaal
XTAL 20                       ;Kristal van 20MHz
TRISA = 0
Dim inbyte As Byte

While 1 = 1

SerIn PORTA.1,17197,[Wait ("Abc"),inbyte] 
PORTA.3 = inbyte
Wend

Dit werkt wel perfect omdat hij de commando's zo vaak stuurt dat er wel een goede tussenzit.

Arco

Special Member

Zoals reeds gezegd, 4mS is heel erg kort. (en waarom de pauze daarna?)
Ik neem aan dat het gewone AM (OOK)modules zijn? Je kunt dan gewoon de input voor een halve seconde hoog maken, en meteen daarna beginnen met het verzenden...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 22 september 2009 21:01:21 schreef pientertje:
het maakt toch niet uit als de één op 4MHz draait en de ander op 20? Ik krijg als het goed is morgen mn tweede breadboardje terug die ik had uitgeleend aan een klasgenoot, dus dan kan ik testen met wat meer afstand ertussen.

Maakt idd wel uit, ik had hetzelfde probleem, zie
http://www.circuitsonline.net/forum/view/76574

marcob

Golden Member

Ik doe het volgende en dat werkt goed.
De zender stuurt eerst een aantal A's daarna een startcode, dan een adres, dan de data. dan nog eens. de startcode, adres en data.

De ontvanger schuift alle data in een Array. Met een functie laat ik de Array controleren of de start code zichtbaar is, en daarna vergelijk ik de eerste data met de tweede. Is deze gelijk dan verwerk ik hem.

zender:

pic basic code:

SerOut PORTA.1,17197, ["AAAAAA", "PW", ADRES, DATA , START, ADRES, DATA]

ontvanger: geleend van Mr.Chaos
http://www.circuitsonline.net/forum/view/61410
Ik heb hem zelf verder uitgebouwd, maar dit is een begin

pic basic code:

Device 16F628A                 	                      ; Gebruik een 16F628A type
CONFIG WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF, HS_OSC  ; INTRC_OSC_NOCLKOUT verwijderd
ALL_DIGITAL TRUE              	   		      ; Alle ingangen digitaal
PORTB_PULLUPS ON                        
declare LCD_RSPIN = PORTA.1      		      ; RS pin declareren
DECLARE LCD_ENPIN = PORTA.0   			      ; EN pin declareren
declare XTAL 4

HSERIAL_BAUD = 1200            			      ; Set baud rate
HSERIAL_RCSTA = %10010000  			      ; Enable serial port and continuous receive
HSERIAL_TXSTA = %00100000  			      ; Enable transmit and asynchronous mode
HSERIAL_CLEAR = ON			              ; Optionally clear the buffer before receiving
	
SYMBOL flash_LED = PORTA.2
SYMBOL int_LED   = PORTA.3        

DIM Received AS BYTE                                  ; Variabelen
DIM Value[4] AS BYTE

clear                                                 ; Initialiseren
DELAYMS 500
cls

START:

  INTCON.7 = 1                                        ; Enable Global Interrupts
  INTCON.6 = 1                                        ; Enable Peripheral Interrupts
  PIE1.5 = 1                                          ; Enable UART Rx Interrupt
  ON_INTERRUPT GOTO INT                               ; If there is UART activity: goto INT
GOTO MAIN                                             ; Skip INT, goto main program

INT:  

  HIGH int_LED					      ; interrupt led aan
  HSERIN [Received]
  Value[0]  = Value[1]				      ; zet ontvangen waarde in de array
  Value[1]  = Value[2]				      ; en schuif al aanwezige waarden door
  Value[2]  = Value[3]
  Value[3]  = Received
  If Value[0] = "P" AND Value[1] = "W" Then           ; password = PW
      PRINT AT 1,1, DEC3 Value[2]
      PRINT AT 2,1, DEC3 Value[3]
  EndIf
  LOW int_LED
  CONTEXT RESTORE                         	      ; Restore the registers and exit
GOTO START                                            ; Goto start so INT will be used again

MAIN:

  HIGH flash_LED				      ; hoofdprogramma laat een ledje knipperen
  DELAYMS 500
  LOW flash_LED  
  DELAYMS 500
GOTO MAIN

End
People tend to overestimate what can be done in one year and to underestimate what can be done in five or ten years
Lucky Luke

Golden Member

Kan ik natuurlijk niet achterblijven:

Voor de zender:
(let wel: dit stuk code is nog niet echt netjes afgerond. Het werkt wel. Baudrate van 4800 blijkt toch goed te gaan. de 04 versie waar ik het over heb: ik sla bij iedere wat ingrijpende wijziging het bestand onder een andere naam op. dit was dus de 4e keer :))
Als je onderstaande compiled en in een 16F628A schiet, en je zend vervolgens data naar de 16f628A op z'n rx pin (4800 8N1, data vooraf laten gaan door "$") en je sluit de zender aan op de tx pin van de 16f628a, dan werkt het. (nouja, voeding en kristal enzo, en er is geloof ik nog een indicatorledje ergens (portb.3)). Portb.3 kan dus ook gebruikt worden om te kijken of de zender klaar is om het volgende byte te encoden en verzenden.

pic basic code:


'******************************************************************
'*  Name    : Zender.BAS                                          *
'*  Author  : Lucas Volwater                                      *
'*  Notice  : Copyright (c) 2009 Lucas Volwater                   *
'*          : All Rights Reserved                                 *
'*  Date    : 14-7-2009                                           *
'*  Version : 1.0                                                 *
'*  Notes   : Verzend een byte hamming(7,4) encoded én            *
'*          : manchester encoded voor draadloze datalink (met FEC)*
'******************************************************************

' In deze 04 versie ga ik data inlezen en daarna weer byte voor byte verzenden.
'dit werkt. Dit is dus eigenlijk de definitieve versie voor de zender (wss kan e.e.a nog wat effiecienter, minder kopieren met vars)

DEVICE = 16F628A 'voor testen 16f648a. Def. versie gaat bij voorkeur in kleinere PIC (SMD en ander type).
CONFIG xt_osc, WDT_off, PWRTE_on, BODEN_On, LVP_off, CP_off, mclre_off
DECLARE XTAL = 4
DECLARE ALL_DIGITAL = 1
DECLARE HSERIAL_BAUD 4800 'zender schijnt geen 4800 aan te kunnen (max 2400). Minizender wel (zelfs 9600).

DIM ingelezen[70] AS BYTE 'groot genoeg hoop ik?
DIM manch_out AS WORD
DIM transmit_1 AS WORD
DIM transmit_2 AS WORD
DIM Byte_to_Transmit AS BYTE
DIM High_nible_to_Encode AS BYTE
DIM Low_nible_to_Encode AS BYTE
DIM nible_to_encode AS BYTE
DIM encoded_nible AS BYTE
DIM Manch_in AS BYTE
DIM index AS BYTE
CLEAR

SYMBOL ctrs = PORTB.3 ; clear to recieve/send
OUTPUT ctrs
GOTO main

encode:

'dit hieronder encoded de nibble hamming(7,4)
' (p1,p2,d1,p3,d2,d3,d4) zie wikipedia hamming(7,4)
encoded_nible = LOOKUP nible_to_encode, [%0000000, %1101001, %0101010, %1000011, %1001100, %0100101, %1100110, %0001111,_
%1110000, %0011001, %1011010, %0110011, %0111100, %1010101, %0010110, %1111111]
RETURN

manchester_encode:

manch_out.0 = Manch_in.0
manch_out.1 =~Manch_in.0 'zou dit werken? (edit: JA) 
'~betekend inverteren, ofwel: als manch_in.0 een 1 was dan wordt manch_out.1 een 0 (en v.v
manch_out.2 = Manch_in.1
manch_out.3 = ~Manch_in.1
manch_out.4 = Manch_in.2
manch_out.5 = ~Manch_in.2
manch_out.6 = Manch_in.3
manch_out.7 = ~Manch_in.3
manch_out.8 = Manch_in.4
manch_out.9 = ~Manch_in.4
manch_out.10= Manch_in.5
manch_out.11= ~Manch_in.5
manch_out.12= Manch_in.6
manch_out.13= ~Manch_in.6
manch_out.14= Manch_in.7
manch_out.15= ~Manch_in.7
RETURN


main:

ctrs = 1        'ready for data         
HSERIN [WAIT ("$"), STR ingelezen]    'lees gegevens in (je moet eerst een $ sturen om 'm te laten lezen
' , dit omdat ik test met een GPS die dat doet)
ctrs = 0        'please wait
ingelezen[68] = 10 'CR en LF toevoegen aan de data
ingelezen[69] = 13
    FOR index = 0 TO 69
    Byte_to_Transmit = ingelezen[index]
    High_nible_to_Encode = Byte_to_Transmit      'eerst het high nible coderen
    High_nible_to_Encode.7 = 0
    High_nible_to_Encode.6 = 0
    High_nible_to_Encode.5 = 0
    High_nible_to_Encode.4 = 0
    nible_to_encode = High_nible_to_Encode
    GOSUB encode

    Manch_in = encoded_nible
    GOSUB manchester_encode
    transmit_1 = manch_out
    Low_nible_to_Encode = 0 'eerst alles op 0
    Low_nible_to_Encode.3 = Byte_to_Transmit.7 'daarna bit voor bit kopieren
    Low_nible_to_Encode.2 = Byte_to_Transmit.6
    Low_nible_to_Encode.1 = Byte_to_Transmit.5
    Low_nible_to_Encode.0 = Byte_to_Transmit.4
    nible_to_encode=Low_nible_to_Encode
    GOSUB encode

    Manch_in = encoded_nible
    GOSUB manchester_encode
    transmit_2 = manch_out
    HSEROUT [%01010101, %10101010, %11001100, transmit_1, transmit_2] '1e 2 waarden zijn "zenderstarters"

    'de %11001100 is waar de ontvanger op locked
    NEXT

GOTO main

Ontvanger:
(ook hier weer: coments waren niet bedoeld voor het hele internet, er kunnen dus wat onbegrijpelijk dingen in staan die nog ergens op sloegen in een vorige versie oid)

pic basic code:


'****************************************************************
'*  Name    : ontvanger.BAS                                     *
'*  Author  : Lucas Volwater                                    *
'*  Notice  : Copyright (c) 2009 Lucas Volwater                 *
'*          : All Rights Reserved                               *
'*  Date    : 14-7-2009                                         *
'*  Version : 1.0                                               *
'*  Notes   : Ontvanger behorend bij de zender                  *
'*          : decodeerd eerst manchester, doet daarna hamming(7,4) foutcorrectie,
'*          : en daarna decodeerd het dat ook tot het oorspr. byte   *
'****************************************************************
' In deze 02 versie probeer ik de snelheid te verhogen.
' 4800 werkt ook! Ontvangercode is nu dus eigenlijk af.

DEVICE = 16F628A 'voor testen 16f628a. Def. versie mogelijk ook, maar liefst kleiner type.
CONFIG xt_osc, WDT_off, PWRTE_on, BODEN_On, LVP_off, CP_off, mclre_off
DECLARE XTAL = 4
DECLARE ALL_DIGITAL = 1
DECLARE HSERIAL_BAUD 4800  'zender kan niet hoger dan 2400 officieel

DIM recieve_1 AS WORD
DIM recieve_2 AS WORD
DIM manch_out AS WORD
DIM manch_in AS BYTE
DIM highnible AS BYTE
DIM lownibble AS BYTE
DIM bitflipped AS BYTE
DIM inputbyte AS BYTE
DIM decoded_nible AS BYTE
DIM byte_to_decode AS BYTE
DIM recieved AS BYTE

GOTO main

manchester_decode: 'er word niet echt gedecodeerd in de zin dat er word gekeken of het klopt dat het volgende bit de inverse is
'wel in de zin van dat de originele data weer terug wordt gehaald...
manch_in.0 = manch_out.0 'deze decodeersubroutine werkt met dezelfde vars als de codeersub, misschien verwarrend, maar coderen
manch_in.1 = manch_out.2 'is het omgekeerde van decoderen en de vars werken ook omgekeerd. in=out 
manch_in.2 = manch_out.4
manch_in.3 = manch_out.6
manch_in.4 = manch_out.8
manch_in.5 = manch_out.10
manch_in.6 = manch_out.12
manch_in.7 = manch_out.14
RETURN

errcorrect:

bitflipped = LOOKUP inputbyte, [0,7,3,4,5,2,6,1,1,6,2,5,4,3,7,0,6,1,5,2,3,4,0,7,7,0,4,3,2,5,1,6,2,5,1,6,7,0,4,3,3,4,0,7,6,1,5,_
2,1,3,7,0,1,6,2,5,5,2,6,1,0,7,3,4,4,3,7,0,1,6,2,5,5,2,6,1,0,7,3,4,2,5,1,6,7,0,4,3,3,4,0,7,6,1,5,2,6,1,5,2,3,4,0,7,7,0,4,3,2,5,1,_
6,0,7,3,4,5,2,6,1,1,6,2,5,4,3,7,0]

    SELECT bitflipped  'die is vreselijk omslachtig... waarom kan het bitnummer geen var zijn?
    CASE 0                        'case 0 hoeft niets geflipped te worden, want 0 betekend: geen errors. Punt 2 is: gaathet wel goed
    'met het extra paritybit? -extra paritybit verwijderd en nog wat gewijzigd. werkt nu
    CASE 1
        inputbyte.6 = ~inputbyte.6 'inverteer bit. (dit bit is omgevallen, inverteren zet het weer recht)
    CASE 2
        inputbyte.5 = ~inputbyte.5
    CASE 3
        inputbyte.4 = ~inputbyte.4
    CASE 4
        inputbyte.3 = ~inputbyte.3
    CASE 5
        inputbyte.2 = ~inputbyte.2
    CASE 6
        inputbyte.1 = ~inputbyte.1
    CASE 7
        inputbyte.0 = ~inputbyte.0
    ENDSELECT
RETURN


decode:

'met deze lookdownlist kun je de originele waarde terugrekenen na foutcorrectie.
decoded_nible = LOOKDOWN byte_to_decode, [%0000000, %1101001, %0101010, %1000011, %1001100, %0100101, %1100110, %0001111,_
%1110000, %0011001, %1011010, %0110011, %0111100, %1010101, %0010110, %1111111]       
RETURN 

main:

HRSIN WAIT (%11001100), recieve_1, recieve_2
manch_out = recieve_1
GOSUB manchester_decode
highnible = manch_in
manch_out = recieve_2
GOSUB manchester_decode
lownibble = manch_in
inputbyte = highnible
GOSUB errcorrect
highnible = inputbyte
inputbyte = lownibble
GOSUB errcorrect
lownibble = inputbyte
byte_to_decode = highnible
GOSUB decode
highnible = decoded_nible
byte_to_decode = lownibble
GOSUB decode
lownibble = decoded_nible
recieved.4 = lownibble.0
recieved.5 = lownibble.1
recieved.6 = lownibble.2
recieved.7 = lownibble.3
recieved.0 = highnible.0
recieved.1 = highnible.1
recieved.2 = highnible.2
recieved.3 = highnible.3
HSEROUT [recieved]
GOTO main
END

Bij die ontvanger: HSERIN laten wachten op iets waar geen foutcorrectie op wordt toegepast is niet zo heel erg slim: dan komt net dat ene stukje niet goed aan en daarmee de hele data ook niet meer... Maar anders wordt gewoon deze foutcorrectie toegepast op alles dat ontvangen wordt, zodat er gewoon allerlij troep uit de ontvanger komt als je eigen zender niet in de lucht is.

Dit is dus niet een afgerond project wat je zo kunt overnemen, maar misschien heb je er toch wat aan. Verander gerust het type PIC of de baudrate of wat dan ook. Het grootste stuk werk van deze code zat 'm vooral in het vooraf uitrekenen van de look up list(s), dus hopelijk kun je die recyclen.

Als ergens een letter lijkt te ontbereken dan is dat waarschijnlijk ook zo, ik heb handmatig een aantal linefeeds weggehaald die teveel verschenen bij het copy-pasten.

Eluke.nl | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)

Dus als ik he goed begrijp werkt jouw systeem zo:

pic1 -> zenderpic -> zender ontvanger -> ontvangpic -> pic2

Lucky Luke

Golden Member

Ja, of je moet de code wat aanpassen. Er is nog ruimte zat. Het is ook meer bedoeld als een opzetje. Je kunt er gewoon een "slimme zender" mee maken, dus idd uC - zenderpic - ontvagerpic - uC, met dat wat kleinere PIC's, maar je kunt ook de zender/ontvangerpic direct iets laten doen met de data. Nouja, iets anders dan encoden/decoden dan...

EDIT @ Pientertje hieronder : bijvoorbeeld ja, voor een draadloze servosturing. Wel de juiste HSERIN/out vervangen natuurlijk. Niet de HSERIN van de ontvanger en de HSEROUT van de zender :P

[Bericht gewijzigd door Lucky Luke op zaterdag 26 september 2009 00:34:28 (11%)

Eluke.nl | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)

Ok dankje. Dar had ik zelf op moeten komen. Gewoon de hserin vervangen door pot en hserout door servo.