Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
I would think it is a same song second verse sort of thing.blueroomelectronics said:I wonder what the playing card variation trick is?
'****************************************************************
'* Name : Switchboard.BAS *
'* Author : G.A. Nijland *
'* Notice : Copyright (c) 2007 *
'* Date : 19-08-2007 *
'* Version : 1.0 *
'* Notes : This software is distributed as is without any *
'* warranty under the GNU GENERAL PUBLIC LICENSE. *
'* Please read 'GPL-3.0.TXT' *
'****************************************************************
Device 16F628A
Config INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL = true
XTAL = 4
'PORTB_PULLUPS
' LET OP: Gebruik voor deze versie nóóit de PULLUPS.
' Daardoor werkt het detectiemechanisme van een losgedraaide bulb niet meer.
' De switches hebben (helaas) een eigen pull up weerstand.
' Misschien de volgende versie...
Include "..\()library\INT_SYMBOLS.bas"
'Een paar hulpsymbolen voor tellen van interrupts
Symbol Prescaler = 256 'Let op: de prescaler wel goed instellen via PS0..2!!
Symbol PulsesPerSecond = (XTAL * (1000000/4)) / (256 * Prescaler)
' Namen voor de lampjes tbv in- en uitschakelen na leermodus
Symbol BulbOnbekend = 0
Symbol Bulb1 = 1
Symbol Bulb2 = 2
Symbol Bulb3 = 3
Symbol Bulb4 = 4
' Symbolen voor in- en uitgeschakelde schakelaars (inverted)
Symbol SW_ON = 0
Symbol SW_OFF = 1
' Poorten switches
Symbol Switch1 = PORTB.3
Symbol Switch2 = PORTB.2
Symbol Switch3 = PORTB.1
Symbol Switch4 = PORTB.0
' Lamp-detect poorten
Symbol LA1_In = PORTB.4
Symbol LA2_In = PORTB.5
Symbol LA3_In = PORTB.7
Symbol LA4_In = PORTB.6
' Uitgangen voor inschakelen lampjes
Symbol LA1_out = PORTA.0
Symbol LA2_out = PORTA.1
Symbol LA3_out = PORTA.3
Symbol LA4_out = PORTA.2
' State symbols voor besturing programma
Symbol LEERMODUS_SW1 = 1 ; Wacht op schakelaar 1
Symbol LEERMODUS_SW2 = 2 ; Wacht op schakelaar 2
Symbol LEERMODUS_SW3 = 3 ; Wacht op schakelaar 3
Symbol LEERMODUS_SW4 = 4 ; Wacht op schakelaar 4
Symbol SPEELMODUS = 5 ; Schakelaars mogen willekeurig worden ingeschakeld
' Vertraginsinstellingen
Symbol RESET_DELAY = 10 ; # seconden voor de PIC reset naar leermodus 1
Symbol SLEEP_DELAY = 45 ; # seconden voor de PIC in slaap valt
Dim Switch1_Target As Byte ; Welk lampje gaat aan wanneer 1 wordt ingeschakeld?
Dim Switch2_Target As Byte ; Welk lampje gaat aan wanneer 2 wordt ingeschakeld?
Dim Switch3_Target As Byte ; Welk lampje gaat aan wanneer 3 wordt ingeschakeld?
Dim Switch4_Target As Byte ; Welk lampje gaat aan wanneer 4 wordt ingeschakeld?
Dim BoardState As Byte ; In welke state zitten we nu?
Dim ResetCount As Byte ; Teller voor terugschakelen naar leermodus sw1.
Dim SleepCount As Byte ; Teller voor in slaap vallen
Dim SecDelay As Byte ; Tellertje voor bijhouden wanneer 1 sec voorbij is
Dim SwitchTarget As Byte ; Buffertje voor inschakelen lampje (parameter). Op basis
; van de waarde hierin, gaat één van de lampjes aan of uit.
Dim SwitchStatus As Bit ; IDem...
Dim SwitchState As Byte ; De toestand van de schakelaars
Dim SwitchStateOld As Byte ; De toestand van de schakelaars 'de vorige keer'
Dim LampState As Byte ; De toestand van de lampjes
Dim LampStateOld As Byte ; De toestand van de lampjes 'de vorige keer'
' Interrupt vlag(gen)
Dim FlagSeconde As Bit ; Er is een seconde verstreken
'-------------------------------------------------------------------------------
ProgramStart:
on_interrupt HandleInterrupt
GoTo Main
'-------------------------------------------------------------------------------
HandleInterrupt:
If T0IF = 1 Then
Dec SecDelay
If SecDelay = 0 Then
SecDelay = PulsesPerSecond
FlagSeconde = 1
End If
T0IF = 0
End If
'RB4..7 interrupt on change werkt helaas (nog) niet...
'In het hoofdprogramma worden de switches en bulbs 'handmatig' afgetest.
HandleInterrupt99:
Context Restore
'-------------------------------------------------------------------------------
Main:
; Hardware configuratie van de PIC
; Poorten instellen voor gebruik van de lampjes en schakelaars
; 76543210
TRISA = %00100000 ; PORTA.5 input (MCLR), de rest output (lampjes schakelen)
TRISB = %11111111 ; Alle PORTB input (schakelaars en lampjes)
Clear
DelayMS 100
; Interrupt flags zetten.
GoSub ConfigInterrupts
; Board reset
MainReset:
GoSub SleepTimerReset
GoSub BoardReset
'-------------------------------------------------------------------------------
; Hier start de centrale verwerkingslus.
; Hoe werkt dit:
; Afhankelijk van de state van het programma, voeren we acties uit.
; In de leermodus leren we achtereenvolgens welke lampjes bij welke schakelaars
; horen. Als we klaar zijn met 'leren', mogen de schakelaars willekeurig worden
; ingeschakeld.
; Als we een lampje losdraaien, dan moeten we de leermodus opnieuw starten.
; Want dan zijn er waarschijnlijk lampjes verwisseld. Dus de status van de lampjes
; controleren we regelmatig.
; Wanneer er 10 seconden geen actie is geweest doen we ook een reset van de leermodus.
; Dit is omdat we mogelijk de dopjes omgewisseld hebben. En dan moeten we die ook
; weer aan nieuw lampjes toekennen.
; Let op: deze reset doen we alleen als er géén schakelaar is omgezet!
; Telkens wanneer een schakelaar wordt ingeschakeld, doen we een reset van deze
; 10-secondenteller. Want dan zijn we bezig met leren of 'spelen'!
While SleepCount > 0
' 1. Haal de state van de schakelaars en lampjes op
GoSub GetExternalState
' 2. Als er met tenminste één van de lampjes iets is gebeurd, dan terug naar leermodus.
' We hoeven hier geen ontdendering te doen. Want of we nu een lampje uit- of indraaien
' en hoe vaak er 'dendert', pas bij overzetten van schakelaars wordt de volgorde
' bepalend. En dan hebben we toch weer een stabiele situatie.
' NB: lampjes wel goed vastdraaien :-)
If LampState <> LampStateOld Then
'Debug modus: als een lampje wordt losgedraaid, kort knipperen.
'LA4_out = 1 ' @@@@
'DelayMS 250
'LA4_out = 0
GoSub SleepTimerReset 'Als een lampje wordt los- of vastgedraaid, dan reset sleep timer
GoSub StartLeermodus 'We starten weer van voren af aan met de leermodus
LampStateOld = LampState 'Tbv het opmerken van de volgende verandering
End If
' 3. Als er een schakelaar is overgehaald, dan moeten we drie dingen doen:
' a. Ontdenderen
' b. Controleren of we in de leermodus zitten.
' Zo ja, dan bij inschakelen van een nieuwe schakelaar, deze bij het
' het lampje vastleggen en de leermodus.
' Bij alleen uitschakelen doen we in de leermodus niets.
' c. Het bijbehorende lampje in- of uitschakelen
If SwitchState <> SwitchStateOld Then
'Debug modus: laat zien dat de schakelactie 'gezien' is.
'LA3_out = 1 ' @@@@
'DelayMS 250
'LA3_out = 0
GoSub SleepTimerReset 'Als een schakelaar wordt bediend, dan reset sleep timer
DelayMS 5 'Ontdendering
' Als we nog niet in speelmodus zitten, moeten we de schakelaars 'leren'
If BoardState <> SPEELMODUS Then GoSub AfhandelenLeermodus
GoSub LampjesTonen 'Lampjes aan of uit
SwitchStateOld = SwitchState 'Tbv het opmerken van de volgende verandering
GoSub ResetCounterReset 'En de reset uitstellen
End If
' 4. Tot slot de tijd-afhankelijke dingen doen.
' a. Controleer of we de 10-seconden reset moeten doen
' b. De sleep-timer ook aflagen zodat bij langere tijd geen actie we stroom kunnen besparen.
If FlagSeconde = 1 Then
FlagSeconde = 0
GoSub CheckResetNaTijd
' En de sleep timer bijwerken
Dec SleepCount
End If
Wend
'Als we hier aankomen, dan zitten we in sleepmodus
GoSub SleepKnipper
'Alle poorten laag
PORTA = 0x00
PORTB = 0x00
'We reageren alleen op een RB0 verandering, maar geen interrupt geven.
'(zie datasheet)
GIE = 0
INTF = 0
INTE = 1
INTEDG = 0 ' RB0 ontwaken bij 'laag'
Sleep
INTF = 0
INTE = 0
GIE = 1
'We gebruiken schakelaar 4 voor het wakker worden (afhankelijk van de config).
'Dus lampje 4 aanzetten om te laten zien dat we 'wakker' zijn én
'wachten tot schakelaar 4 weer is uitgezet.
DelayMS 5 'Ontdenderen
LA4_out = 1
While Switch4 = 0
Wend
DelayMS 10 'Ontdenderen
LA4_out = 0
GoTo MainReset 'We beginnen weer van voren af aan...
'-------------------------------------------------------------------------------
SleepKnipper:
'Knipper een paar keer met lampje 4
'(voornamelijk bij 'in slaap vallen')
LA4_out = 1
DelayMS 250
LA4_out = 0
DelayMS 250
LA4_out = 1
DelayMS 250
LA4_out = 0
DelayMS 250
Return
AfhandelenLeermodus:
'Hier gebeurt het echte werk. Afhankelijk van de status controleren we welk
'lampje we aan welke schakelaar moeten koppelen.
'Maar dat doen we alleen als we in de leermodus zitten.
'We bepalen eerst welke lamp we nog moeten vastleggen. Dat doen we door te kijken
'naar hoeveel switchtargets we al hebben vastgelegd.
SwitchTarget = Bulb1
If Switch1_Target <> 0 Then Inc SwitchTarget
If Switch2_Target <> 0 Then Inc SwitchTarget
If Switch3_Target <> 0 Then Inc SwitchTarget
If Switch4_Target <> 0 Then Inc SwitchTarget
'Switchtarget bevat nu het lampnummertje.
'Nu alleen nog kijken welke schakelaar er is geschakeld.
'Let op: als van deze schakelaar de switch-target al is ingevuld, dan vullen we die
'uiteraard niet nog een keer in!
'Dus we kunnen in de leermodus ook alle lampjes achter elkaar aanzetten. Dus een voor
'een inschakelen is niet per so noodzakelijk!
'
'Controles:
' - is de schakelaar ingeschakeld.
' - indien nee, overslaan
' - zo ja, heeft die al een doel-lampje?
' - indien ja, dan deze switch overslaan.
' - indien nee: deze invullen en terugkeren.
If Switch1 = SW_ON Then
If Switch1_Target = BulbOnbekend Then
Switch1_Target = SwitchTarget
Inc BoardState
Return
End If
End If
If Switch2 = SW_ON Then
If Switch2_Target = BulbOnbekend Then
Switch2_Target = SwitchTarget
Inc BoardState
Return
End If
End If
If Switch3 = SW_ON Then
If Switch3_Target = BulbOnbekend Then
Switch3_Target = SwitchTarget
Inc BoardState
Return
End If
End If
If Switch4 = SW_ON Then
If Switch4_Target = BulbOnbekend Then
Switch4_Target = SwitchTarget
Inc BoardState
Return
End If
End If
Return
LampjesTonen:
'Afhankelijk van welke schakelaars er zijn ingedrukt, schakelen we lampjes in.
'We moeten daarbij steeds het lampje schakelen, dat er op basis van de 'leermodus' bij hoort.
SwitchTarget = Switch1_Target: SwitchStatus = Switch1: GoSub SwitchBulb
SwitchTarget = Switch2_Target: SwitchStatus = Switch2: GoSub SwitchBulb
SwitchTarget = Switch3_Target: SwitchStatus = Switch3: GoSub SwitchBulb
SwitchTarget = Switch4_Target: SwitchStatus = Switch4: GoSub SwitchBulb
Return
SwitchBulb:
'We krijgen de geinverteerde status binnen (veroorzaakt door de 'pull down' van de switches).
'Dus 'hoog' is eigenlijk lampje uit. Daarom inverteren we die status hier weer.
SwitchStatus = SwitchStatus ^ 1
'Afhankelijk van de waarde in SwitchTarget gaan we een lampje schakelen.
Select SwitchTarget
Case Bulb1: LA1_out = SwitchStatus
Case Bulb2: LA2_out = SwitchStatus
Case Bulb3: LA3_out = SwitchStatus
Case Bulb4: LA4_out = SwitchStatus
End Select
Return
GetExternalState:
' We gaan de status van de lampjes en schakelaars ophalen.
' Beide zitten op PORTB, dus die kunnen we ineens ophalen.
' De lampjes zitten in de hoge 4 bits. Dus die moeten we eruit filteren
' Daarna de schakelaars filteren op de 4 lage bits.
SwitchState = PORTB
LampState = (SwitchState >> 4) & 0x0F
SwitchState = SwitchState & 0x0F
Return
CheckResetNaTijd:
'Controler of we een aantal seconden niets hebben gedaan.
'Als dat zo is, dan resetten we de leerodus.
Dec ResetCount
If ResetCount = 0 Then GoSub StartLeermodus
Return
BoardReset:
'Alle lampjes uit forceren
LA1_out = 0
LA2_out = 0
LA3_out = 0
LA4_out = 0
; We beginnen met de leermodus
GoSub StartLeermodus
Return
'NB: de gosub en return kunnen eventueel worden weggelaten.
'Maar als er vanwege debuggen statements bijkomen, is dat weer minder handig...
StartLeermodus:
BoardState = LEERMODUS_SW1 ' De leermodus begint bij switch 1
Switch1_Target = BulbOnbekend ' We weten nog niet wat we inschakelen.
Switch2_Target = BulbOnbekend ' ...
Switch3_Target = BulbOnbekend ' ...
Switch4_Target = BulbOnbekend ' ...
GoSub ResetCounterReset
Return
ResetCounterReset:
; Start opnieuw met tellen voor reset
SecDelay = PulsesPerSecond ' Interrupt delay weer op maximum zetten
ResetCount = RESET_DELAY ' Secondenteller ook weer op maximum.
FlagSeconde = 0 ' En wachten op nieuwe seconde-interrupts
Return
SleepTimerReset:
SleepCount = SLEEP_DELAY
Return
ConfigInterrupts:
; Timer 0: we werken op 4MHz, dus met maximale prescaler zo'n 15 interrupts per seconde
GIE = 0 ' Effe geen interrupts
PSA = 0 ' Prescaler voor Timer0
PS0 = 1 ' ...
PS1 = 1 ' ...
PS2 = 1 'Prescaler 111: maximale waarde van 256.
T0CS = 0 'Timer0 werkt op de interne clock.
TMR0 = 0 ''Harde reset' van timer0.
T0IE = 1 'Timer0 interrupts ingeschakeld
SecDelay = PulsesPerSecond 'Begin met aftellen voor 1 seconde
GIE = 1 'Go...
Return
End
I agree regarding the power LED and the DIP switch.blueroomelectronics said:Well I guess you might as well build it right. We've got the free I/O and it can still be built with or without the current sense.
As for the DIP switch that's so old school, we could add a configuration jumper and use the switches to set the mode(s)
So let's reshuffle things a little
PORTA 0-3 the lamp drivers
PORTA 4 setup jumper
PORTA 5 MCLR
PORTA 6 mode/setup LED
PORTB 0-3 the current sense inputs
PORTB 4-7 the switches
PS don't really need a power LED
Looks like they've used painted wooden drawer knobs to slip over the bat handles of the switches.blueroomelectronics said:Nice photo with PIC from the Dutch forums
The 628A datasheet saysblueroomelectronics said:Just remembered, RA3 is open collector on a 16F628A, so lets move the lamp on RA3 to RA7 *makes for a fun program too
Also skip the current sense stuff, I can't see any real advantage.
Did not see where RA3 was open collector.RA4 is a Schmitt Trigger
input and an open drain output. Port RA4 is multiplexed
with the T0CKI clock input.
wmmullaney said:I am looking at the datasheet now, all I see is an INTOSC with clkout or without. How do you get the lower feq.?
Pommie said:You don't need to sense current to know if a bulb is present or not. Just put 10k resistors across the transistors and connect the collectors to spare inputs. When the bulb is off the input will be high if the bulb is present, low if removed. No need for any ADCs.
Mike.