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
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Er zijn inderdaad helemaal geen PIC's 10Fxx of 12Fxx met USART. Daarom zijn het ook low-end devices.
Dat wordt dus bit-bangen...
klein is fijn
Moderator
Dan is het de gammelheid van Proton, bij software UART zou de kristalsnelheid helemaal niets uit moeten maken.
rew
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
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).
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:
; 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:
; 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
Frits Kieftenbelt
Ohm sweet Ohm | www.picbasic.nl
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.
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
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bij 4MHz is de afwijking +0.16%(1202 Bd), bij 20MHz is dat +1.75%(1221 Bd)...
Dat is dus behoorlijk wat...
@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
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
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?
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?
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
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?
Op 28 augustus 2009 15:04:38 schreef shiptronic:
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 WATCHDOGwaarom 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?