Kristal en Baudrate

Ik heb een simpele rookmelder omgebouwd zodat deze bij een alarm
middels een 12F629 met 4Mhz kristal een seriele code uitstuurd met 1200 baud (mbv een 433 Mhz module).

Ook heb ik een 433 Mhz ontvanger gekoppeld aan een 16F628 ook ingesteld op 1200 Baud, lopend op een 20Mhz kristal.

Mijn vraag; waarom werkt dit alleen als ik voor beide pics een 4 Mhz kristal gebruik en niet de configuratie zoals hierboven genoemd (4Mhz & 20 Mhz kristal)? 1200 baud is toch 1200 baud?

(ik werk met Proton Picbasic)

klein is fijn

Moderator

Als PIC's op dezelfde manier een UART clock maken als AVR's, dan wordt de system clock gewoon een x aantal keer gedeeld. Dat x aantal keer is maar met stappen instelbaar, waardoor je een afwijking krijgt. Bij een systeemclock van 1MHz is die afwijking anders dan bij een clock van 3MHz (4 & 12MHz / 4), waarmee de baudrate ook anders is.
Als die teveel verschilt -> geen feest bij de ontvanger.

De datasheet zegt daar waarschijnlijk meer over.

Als ik even snel de datasheet bekijk kom ik geen u(s)art tegen. Dat betekent dus dat je het software matig moet doen. Waarschijnlijk is de min/max snelheid afhankelijk van het xtal.

Arco

Special Member

Er zijn inderdaad helemaal geen PIC's 10Fxx of 12Fxx met USART. Daarom zijn het ook low-end devices.
Dat wordt dus bit-bangen...

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

Moderator

Dan is het de gammelheid van Proton, bij software UART zou de kristalsnelheid helemaal niets uit moeten maken.

Nou, dan nog kan je afwijkingen krijgen doordat ie maar een beperkte resolutie heeft.... Anderzijds, 1200 baud is wel ERG langzaam, en dan moet de resolutie ondertussen wel voldoende zijn om ook 1210 baud te doen...

De meest waarschijnlijke oorzaak lijkt me dat je vergeet om in geval van 20MHz kristal je software dat te vertellen. De software laat alles van de klok afhangen. Dus als je op 4MHz 1200 baud maakt, wordt dat vanzelf 6000 baud op 20MHz. Eventueel kan je het ding op 20MHz vertellen dat je 240 baud wilt hebben, als je niet kunt vinden waar je de systeemklok instelt. (of het lastig is omdat het in de software maar 1x ingesteld kan worden en niet voor de twee sources verschillend).

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Shiptronic

Overleden

post je config eens, dan kunnen we wat zien

Wie de vraag stelt, zal met het antwoord moeten leren leven.

Hierbij de schema's en software:

Overigens gebruik ik bij de zender 12F629 geen UART maar het commando 'Serout' en bij de ontvanger wel 'Hserin'

Schema Ontvanger (bovenste gedeelte):
http://www.uploadarchief.net/files/download/wireless_interface.png

Schema Rookmelder / Zender:
http://www.uploadarchief.net/files/download/smoke_transmitter.png

Source Zender:

code:


; Smoke Transmitter

Device 12F629 
Config CPD_OFF, CP_OFF, BODEN_OFF, MCLRE_OFF, PWRTE_ON, WDT_ON, XT_OSC
Declare Watchdog = On
All_Digital True   
Xtal = 4       

; PSA Watchdog
Symbol PS0 = OPTION_REG.0      ' Prescaler Rate Select
Symbol PS1 = OPTION_REG.1      ' Prescaler Rate Select
Symbol PS2 = OPTION_REG.2      ' Prescaler Rate Select
Symbol PSA = OPTION_REG.3      ' Prescaler Assignment

Dim test_teller As Word
Dim teller2 As Word
Dim smokealarm As Bit
Dim teller As Word
Dim notactive_timer As Word
Dim tel As Word
Dim x As Byte
Dim BD1 As Byte
Dim aantal_lowbat As Byte

;        76543210
PORTB = %00000000 
TRISB = %00000010 

; Initialize watchdog
PSA = 1     ;Assign postscaler to watchdog
PS0 = 1     ;Postscaler = 1:128 (bit 2^3 = 8 of divider -> 1:128. Means: 18ms * 128 ~ 2.3 sec approx) 
PS1 = 1
PS2 = 1

Clear ; wis alle ram geheugen
DelayMS 500 ;stabilisatie signalen
 
INTCON.7 = 0    ; Interupt Handler uit zetten
INTCON.3 = 1    ; GPIO Port Change Interupt enable
IOC = %00000010 ;Interrupt On Change voor GPIO.1 inschakelen
 
; ======= HOOFDLUS ========

Main:
BD1  = PORTB                ;Lees "This wil end the mismatch condition" in de datasheet
INTCON.0 = 0    
Sleep


If STATUS.4 = 0 Then 
    Inc test_teller ; WDT reset
        If test_teller > 1000 Then 
            Clear test_teller
            GoTo test_signal
        EndIf
EndIf

If STATUS.4 = 1 Then GoTo verder

GoTo Main


verder:
    Inc notactive_timer
    If notactive_timer > 7000 Then GoTo sleepmode  ; meer als 70 seconden geen alarm meer gehoord ?
    
    If smokealarm = 1 Then Inc teller2 
    
    If teller2 > 1500 Then                         ; test of er 15 seconden aan stilte is verstreken na een rookalarm
        Clear smokealarm
        Clear teller2
        GoTo Main
    EndIf
    
    If PORTB.1 = 1 Then GoTo check_count ; sirene uitgang hoog
    DelayMS 10
GoTo verder


sleepmode:
    If PORTB.1 = 0 Then ; Geen sirene en geen lowbatmeldingen?
        DelayMS 100
            If PORTB.1 = 0 Then               ; Nogmaals testen
                  DelayMS 50
                  Clear notactive_timer
                  GoTo Main
            EndIf
    EndIf
GoTo Main ; voor de zekerheid

check_count:
Clear notactive_timer
tel = Counter PORTB.1, 3000
    If tel > 200 Then fire
GoTo Main
;===================== Sirene rookmelder is aan ========================
fire:
    Clear teller2
    smokealarm = 1 
    High PORTB.0    ; Zender aan
    DelayMS 1000    ; stabilisatie zender
    SerOut PORTB.2, 813, [170, 170, 170, 170, 170, 170, 170]
    For x = 1 To 14
    SerOut PORTB.2, 813, [23, 36, 73, 9, 16, 1]
    Next x
    Low PORTB.0     ; Zender uit
    DelayMS 2000    ; 3 seconden wachten alvorens weer te testen
GoTo verder   

test_signal:
    High PORTB.0    ; Zender aan
    DelayMS 1000    ; stabilisatie zender
    SerOut PORTB.2, 813, [170, 170, 170, 170, 170, 170, 170]
    For x = 1 To 14
    SerOut PORTB.2, 813, [23, 36, 73, 9, 16, 3]
    Next x
    Low PORTB.0     ; Zender uit
GoTo Main   

Ontvanger:

code:


; Wireless Interface (Receiver part) 434Mhz
; SOFTWARE V1.0 - 2009

Device 16F628A
Config hs_osc, wdt_on, pwrte_on, lvp_off, boden_off, mclre_off
Declare Watchdog = On

All_Digital True ;alle ingangen digitaal
Xtal = 20 ;gebruik een kristal van 20mhz
Hserial_Baud = 1200 ;transmissiesnelheid van de data over de bus
Hserial_RCSTA = %10010000 ;bit7: Enable serial port / bit4: continu ontvangen
Hserial_TXSTA = %00000000 ;bit5: transmitpin uitgeschakeld(TXEN(transmit Enable) = 0)

; PSA WATCHDOG
Symbol PS0 = OPTION_REG.0      ' Prescaler Rate Select
Symbol PS1 = OPTION_REG.1      ' Prescaler Rate Select
Symbol PS2 = OPTION_REG.2      ' Prescaler Rate Select
Symbol PSA = OPTION_REG.3      ' Prescaler Assignment

; Initialize watchdog
PSA = 1     ;Assign postscaler to watchdog
PS0 = 1     ;Postscaler = 1:128 (bit 2^3 = 8 of divider -> 1:128. Means: 18ms * 128 ~ 2.3 sec approx) 
PS1 = 1
PS2 = 1

;poortnamen
Dim teller As Byte
Dim coun As Byte
Dim alarm_detected As Bit
Dim inhoud[32] As Byte
Dim ontvang_Commando As Byte
Dim y As Byte

Dim rookmelder_woonkamer_alarm As Bit
Dim rookmelder_woonkamer_lowbat As Bit
Dim rookmelder_woonkamer_test As Bit
Dim rookmelder_woonkamer_alarmhersteld As Bit
Dim rookmelder_garage_alarm As Bit
Dim rookmelder_garage_lowbat As Bit
Dim rookmelder_garage_test As Bit
Dim rookmelder_garage_alarmhersteld As Bit
Dim rookmelder_overloop_alarm As Bit
Dim rookmelder_overloop_lowbat As Bit
Dim rookmelder_overloop_test As Bit
Dim rookmelder_overloop_alarmhersteld As Bit
Dim rookmelder_bijkeuken_alarm As Bit
Dim rookmelder_bijkeuken_lowbat As Bit
Dim rookmelder_bijkeuken_test As Bit
Dim rookmelder_bijkeuken_alarmhersteld As Bit
Dim test_timer As Word

Dim alarm_timer As Word

Dim test_aantal_garage As Byte
Dim test_aantal_overloop As Byte

Dim woonkamer_lowbat_verzonden As Bit
Dim garage_lowbat_verzonden As Bit
Dim overloop_lowbat_verzonden As Bit
Dim bijkeuken_lowbat_verzonden As Bit
Dim test_aantal_woonkamer As Bit         

Dim test_aantal_bijkeuken As Bit   
Dim alarm_aantal_wkmr As Byte
Dim alarmhersteld_verz_wkmr As Bit
Dim alarm_aantal_gar As Byte
Dim alarmhersteld_verz_gar As Bit	
Dim alarm_aantal_overl As Byte
Dim alarmhersteld_verz_overl As Bit
Dim alarm_aantal_bij As Byte
Dim alarmhersteld_verz_bij As Bit



;        76543210
PORTA = %00000000 ;PORTA poorten laag
PORTB = %00000000 ;PORTB poorten laag
TRISA = %00000000 
TRISB = %00000010 

Clear ; wis alle ram geheugen
DelayMS 500 ;stabilisatie signalen


INTCON.7 = 1 ;GIE(global Interrupt Enable) activeren
INTCON.6 = 1 ;PEIE(peripheral Interrupt Enable) activeren
PIE1.5 = 1 ;RCIE(usart receive Interrupt Enable) activeren

On_Interrupt GoTo interruptafhandeling ;spring naar label als data is ontvangen door de usart

GoTo main

interruptafhandeling:
HSerIn [ontvang_Commando]
inhoud[teller] = ontvang_Commando
   If teller > 15 Then               ; Meer als 15 bytes ontvangen? Dan test de string
        For coun = 1 To 7
            If inhoud[coun] = 23 Then
                If inhoud[coun+1] = 36 Then
                    If inhoud[coun+2] = 73 Then 
                        If inhoud[coun+3] = 9 Then
                            If inhoud[coun+4] = 16 Then
                               
                               ; Huiscode is correct
                               ; Nu testen soort melding
                                
                                                              
                                If inhoud[coun+5] = 1 Then rookmelder_woonkamer_alarm = 1
                                ;If inhoud[coun+5] = 2 Then rookmelder_woonkamer_lowbat = 1
                                If inhoud[coun+5] = 3 Then rookmelder_woonkamer_test = 1
                                ;If inhoud[coun+5] = 4 Then rookmelder_woonkamer_alarmhersteld = 1
                                                        
                                If inhoud[coun+5] = 5 Then rookmelder_garage_alarm = 1
                                ;If inhoud[coun+5] = 6 Then rookmelder_garage_lowbat = 1
                                If inhoud[coun+5] = 7 Then rookmelder_garage_test = 1
                                ;If inhoud[coun+5] = 8 Then rookmelder_garage_alarmhersteld = 1
                                
                                If inhoud[coun+5] = 9 Then rookmelder_overloop_alarm = 1
                                ;If inhoud[coun+5] = 10 Then rookmelder_overloop_lowbat = 1
                                If inhoud[coun+5] = 11 Then rookmelder_overloop_test = 1
                                ;If inhoud[coun+5] = 12 Then rookmelder_overloop_alarmhersteld = 1
                                
                                If inhoud[coun+5] = 13 Then rookmelder_bijkeuken_alarm = 1
                                ;If inhoud[coun+5] = 14 Then rookmelder_bijkeuken_lowbat = 1
                                If inhoud[coun+5] = 15 Then rookmelder_bijkeuken_test = 1
                                ;If inhoud[coun+5] = 16 Then rookmelder_bijkeuken_alarmhersteld = 1
                            
                            EndIf
                        EndIf
                    EndIf
                EndIf
            EndIf
        Next coun
    teller = 1    
    EndIf
Inc teller
Clear ontvang_Commando
Context Restore ;restore registers, ga terug naar plek waar Interrupt ontstond
Return ; extra failsafe                           

 
; ======= HOOFDLUS ========
main:
clrwdt

 
If rookmelder_woonkamer_alarm = 1 Then
    Clear rookmelder_woonkamer_alarm
    DelayMS 100 ; even wachten
     If rookmelder_woonkamer_alarm = 1 Then 
        SerOut PORTA.2, 16780, [30]
        DelayMS 100
        Clear rookmelder_woonkamer_alarm
        Inc alarm_aantal_wkmr          ; tel het aantal dat er alarm is ontvangen
        Clear alarmhersteld_verz_wkmr  ; het verzenden van een herstelbericht mag weer
     EndIf 
Endif

If rookmelder_woonkamer_test = 1 Then
    Clear rookmelder_woonkamer_test
    DelayMS 100 ; even wachten
    If rookmelder_woonkamer_test = 1 Then 
        DelayMS 1000
        Clear rookmelder_woonkamer_test
        Inc test_aantal_woonkamer         
    EndIf
EndIf 


If rookmelder_garage_alarm = 1 Then
    Clear rookmelder_garage_alarm
    DelayMS 100 ; even wachten
    If rookmelder_garage_alarm = 1 Then 
        SerOut PORTA.2, 16780, [34]
        DelayMS 100
        Clear rookmelder_garage_alarm
        Inc alarm_aantal_gar          ; tel het aantal dat er alarm is ontvangen
        Clear alarmhersteld_verz_gar  ; het verzenden van een herstelbericht mag weer
    EndIf
EndIf 

If rookmelder_garage_test = 1 Then
    Clear rookmelder_garage_test
    DelayMS 100 ; even wachten
    If rookmelder_garage_test = 1 Then 
        DelayMS 1000
        Clear rookmelder_garage_test
        Inc test_aantal_garage         
    EndIf
EndIf 

If rookmelder_overloop_alarm = 1 Then
    Clear rookmelder_overloop_alarm
    DelayMS 100 ; even wachten
    If rookmelder_overloop_alarm = 1 Then 
        SerOut PORTA.2, 16780, [38]
        DelayMS 100
        Clear rookmelder_overloop_alarm
        Inc alarm_aantal_overl          ; tel het aantal dat er alarm is ontvangen
        Clear alarmhersteld_verz_overl  ; het verzenden van een herstelbericht mag weer
    EndIf
EndIf 

If rookmelder_overloop_test = 1 Then
    Clear rookmelder_overloop_test
    DelayMS 100 ; even wachten
    If rookmelder_overloop_test = 1 Then 
        DelayMS 1000
        Clear rookmelder_overloop_test
        Inc test_aantal_overloop         
    EndIf
EndIf 


If rookmelder_bijkeuken_alarm = 1 Then
    Clear rookmelder_bijkeuken_alarm
    DelayMS 100 ; even wachten
    If rookmelder_bijkeuken_alarm = 1 Then 
        SerOut PORTA.2, 16780, [42]
        DelayMS 100
        Clear rookmelder_bijkeuken_alarm
        Inc alarm_aantal_bij          ; tel het aantal dat er alarm is ontvangen
        Clear alarmhersteld_verz_bij  ; het verzenden van een herstelbericht mag weer
    EndIf
EndIf 


If rookmelder_bijkeuken_test = 1 Then
    Clear rookmelder_bijkeuken_test
    DelayMS 100 ; even wachten
    If rookmelder_bijkeuken_test = 1 Then 
        DelayMS 1000
        Clear rookmelder_bijkeuken_test
        Inc test_aantal_bijkeuken         
    EndIf
EndIf 

; =================== TEST OF ALARM IS HERSTELD =================

If alarm_timer > 1500 Then  ; meer als 15 seconden verstreken?
        
    If alarm_aantal_wkmr < 2 And alarmhersteld_verz_wkmr = 0 Then 
        SerOut PORTA.2, 16780, [31]
        DelayMS 100
        alarmhersteld_verz_wkmr = 1
    EndIf 

    If alarm_aantal_gar < 2 And alarmhersteld_verz_gar = 0 Then 
        SerOut PORTA.2, 16780, [35]
        DelayMS 100
        alarmhersteld_verz_gar = 1
    EndIf 
    
    If alarm_aantal_bij < 2 And alarmhersteld_verz_bij = 0 Then 
        SerOut PORTA.2, 16780, [39]
        DelayMS 100
        alarmhersteld_verz_bij = 1
    EndIf 
    
    If alarm_aantal_overl < 2 And alarmhersteld_verz_overl = 0 Then 
        SerOut PORTA.2, 16780, [43]
        DelayMS 100
        alarmhersteld_verz_overl = 1
    EndIf 
    
    
    Clear alarm_timer  ; zet timer weer op 0  
    
    Clear alarm_aantal_wkmr
    Clear alarm_aantal_gar
    Clear alarm_aantal_bij
    Clear alarm_aantal_overl

EndIf

;======================= TEST OF TESTMELDING om de 45 minuten is ontvangen =============================

If test_timer > 1440000 Then ; meer als 4 uur verstreken?
        Clear test_timer
        
        If test_aantal_woonkamer < 2 Then 
            SerOut PORTA.2, 16780, [33]
            DelayMS 100
        EndIf 
        
        If test_aantal_garage < 2 Then 
            SerOut PORTA.2, 16780, [37]
            DelayMS 100
        EndIf 
        
        If test_aantal_overloop < 2 Then 
            SerOut PORTA.2, 16780, [41]
            DelayMS 100
        EndIf 
        
        If test_aantal_bijkeuken < 2 Then 
            SerOut PORTA.2, 16780, [45]
            DelayMS 100
        EndIf 
        
        Clear test_aantal_woonkamer            
        Clear test_aantal_garage            
        Clear test_aantal_overloop             
        Clear test_aantal_bijkeuken            
EndIf

DelayMS 10
Inc test_timer
Inc alarm_timer
GoTo main   

Maak nou eerst een klein testprogrammaatje waarmee je de verbinding aan de praat krijgt.
Het is me teveel werk (sorry) om de hele code hierboven door te spitten, ook voor jezelf wordt het onoverzichtelijk omdat de fout ook elders in je code kan zitten.
Dus... minimale code maken om de boel aan de praat te krijgen en dan gaan uitbouwen.
Overigens wordt de Baudsnelheid wel degelijk aangepast aan de oscillatorfrequentie door Proton.

Ohm sweet Ohm | www.picbasic.nl

Als ik voor beide schakelingen een 4 Mhz kristal gebruik en natuurlijk de 'DECLARE XTAL =' regel aanpas in de software, werkt het gewoon allemaal prima!

Arco

Special Member

Bij 4MHz is de afwijking +0.16%(1202 Bd), bij 20MHz is dat +1.75%(1221 Bd)...
Dat is dus behoorlijk wat...

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

@Arco; vandaar de miscommunicatie. Wat zou ik eraan kunnen doen, behalve dan voor beiden hetzelfde kristal gebruiken.

Ik wil graag de rookmelders niet op 20Mhz laten draaien ivm het stroomverbruik wat behoorlijk toeneemt bij 20Mhz en aangezien het om een batterijvoeding gaat...

Bij al mijn overige schakelingen heb ik 20Mhz kristallen bij gebruikt dus alles ombouwen naar 4Mhz is eigenlijk ook geen optie.

Arco

Special Member

Als je de SLEEP mode gebruikt zoals eerder besproken, maakt 4 of 20MHz weinig uit.
Het jaarlijks stroomgebruik neemt dan toe met zo'n 0.2mA.
De 0.16% afwijking geldt trouwens voor de hardware USART.
Voor de Proton software versie zijn waarschijnlijk geen gegevens beschikbaar?

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

Overleden

code:




Hserial_Baud = 1200 ;transmissiesnelheid van de data over de bus
Hserial_RCSTA = %10010000 ;bit7: Enable serial port / bit4: continu ontvangen
Hserial_TXSTA = %00000000 ;bit5: transmitpin uitgeschakeld(TXEN(transmit Enable) = 0)

; PSA WATCHDOG

waarom mist ik dit bij de source van de zender?

Wie de vraag stelt, zal met het antwoord moeten leren leven.
Arco

Special Member

Ik gebruik zelf geen Proton Basic, maar ik neem aan dat Hserial_xxx alleen voor de hardware USART is, en niet van toepassing op de software oplossing?

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

Op 28 augustus 2009 15:04:38 schreef shiptronic:

code:




Hserial_Baud = 1200 ;transmissiesnelheid van de data over de bus
Hserial_RCSTA = %10010000 ;bit7: Enable serial port / bit4: continu ontvangen
Hserial_TXSTA = %00000000 ;bit5: transmitpin uitgeschakeld(TXEN(transmit Enable) = 0)

; PSA WATCHDOG

waarom mist ik dit bij de source van de zender?

De declaratieregels mbt Hserial zijn alleen voor de usart niet voor de Serout opdrachten. Vandaar dat ze niet bij de zender aanwezig zijn

Op 28 augustus 2009 14:44:28 schreef Arco:
Als je de SLEEP mode gebruikt zoals eerder besproken, maakt 4 of 20MHz weinig uit.
Het jaarlijks stroomgebruik neemt dan toe met zo'n 0.2mA.
De 0.16% afwijking geldt trouwens voor de hardware USART.
Voor de Proton software versie zijn waarschijnlijk geen gegevens beschikbaar?

Heb nu alles op 20Mhz lopen, alleen nu blijkt dat de 16F629 niet op 3V loopt met een 20Mhz kristal!

Ik val dus van de regen in de drup. Ik heb wel van die low drop 2950 regulators om van 9 naar 5v te gaan maar die verbruiken nog 80uA in rust, dus dat houd dat 9V blokje niet lang uit in de rookmelder

Iemand nog andere idieen?