Gebruik je soms pwm_init of zo? (die regelt alles natuurlijk ook al)
Dit topic is gesloten
Special Member
Gebruik je soms pwm_init of zo? (die regelt alles natuurlijk ook al)
Golden Member
Nee, geen Init. wel:
pic basic code:
PWM1_Remappable_START()
Wellicht dat die het regelt?
Golden Member
Ik vroeg me nog iets anders af:
Ik gebruik de Software I2C.
Is het dan eigenlijk nog nodig op externe pull-ups weerstanden voor de SCL en SDA te gebruiken? Ik heb het wel gedaan, maar vroeg me af of dat wel moet. Omdat je immers geen hardware I2C bus gebruikt...
Special Member
Zou kunnen dat die start wat doet met de settings. (kun je in de asm of lst file zien...)
Pull-ups moet altijd bij i2c. Hard of softwarematig maakt daarin geen verschil. Waarde hangt af van de bussnelheid, belasting, en kabellengte.
Golden Member
Op 4 maart 2021 21:43:53 schreef Arco:
Zou kunnen dat die start wat doet met de settings. (kun je in de asm of lst file zien...)
Pull-ups moet altijd bij i2c. Hard of softwarematig maakt daarin geen verschil. Waarde hangt af van de bussnelheid, belasting, en kabellengte.
Tja, ik heb maar 4K7 genomen, komt redelijk vaak voor in schema's.
Daarnaast, de PIC heeft 2 Poorten voor de ICSDAT en ICSCLK, waarmee je de PIC programmeert.
Nu gebruik ik deze poorten ook voor andere dingen, ervan uitgaande dat de ICS maar even nodig is voor het flashen.
Is dat zo? (m.a.w. er kleven geen bezwaren aan? Anders zou het je 2 poorten kosten)
Golden Member
Voor de liefhebbers:
Dit is uiteindelijk het project sterrenhemel geworden.
Het is geschreven in MikroBasic, met als processor de PIC16F18857.
Het is een sterrenhemel, bestaande uit 8 panelen van 120 * 60 cm, dus in totaal een oppervlakte van 240 * 240 cm.
Ieder paneel heeft 64 leds.
Daarbij hebben 5 percelen een oranje led, die de planeet Mars voorstelt.
Die verschuift gedurende de nacht langs de hemel.
Één paneel is voorzien van gele ledjes, dis als maan fungeren. De schijngestaltes worden weergegeven.
Er zit een DS1307 RTC klokmodule in, waardoor de sterren de tijd kunnen weergeven.
Het programmma bevat 10 functies, met wat 'speeltjes' erbij in.
Dank aan iedereen, in het bijzonder aan Arco, voor de bijdrage die ik kreeg om dit te maken.
Golden Member
Ik hwb voor de controle of de I2C bus vrij is het volgende:
pic basic code:
'====================================================================================================
Sub Procedure Lcd_WrDat(Dim pDat As Byte) 'Write data to display
'====================================================================================================
[b]While (I2C1_Is_Idle) = 0 wend[/b]
I2C1_Start()
I2C1_Wr(0x78)
I2C1_Wr(0x40)
I2C1_Wr(pDat)
Delay_ms(1)
I2C1_Stop()
End Sub
Er kleeft wel een nadeel aan deze constructie: Als er iets is dat veroorzaakt dat de I2C bus niet vrij is (bv slecht draadcontact naar display o.i.d.) dan betekent dat meteen dat alles 'hangt' en de processor wacht op iets dat niet gaat gebeuren.
Is er wellicht en betere methode, waarbij je bv een 'error' afvangt maar het programma wel doorloopt?
Ter illustratie: ik had dit met mijn e-deurbel. Het displaytje had een slecht Dupont contact (meteen vervangen natuurlijk), maar het resultaat was bonkende mensen op de deur omdat de bel het niet meer deed...
Special Member
Je kunt er een time-out inbouwen:
pic basic code:
Const TIME_OUT = 100
Dim Cnt As Byte
'====================================================================================================
Sub Procedure Lcd_WrDat(Dim pDat As Byte) 'Write data to display
'====================================================================================================
For Cnt = 1 To TIME_OUT
If I2C1_Is_Idle Then Break End If 'Exit if idle
Delay_ms(1) 'Optional delay
Next Cnt
If Cnt < TIME_OUT Then
I2C1_Start()
I2C1_Wr(0x78)
I2C1_Wr(0x40)
I2C1_Wr(pDat)
Delay_ms(1)
I2C1_Stop()
End If
End Sub
Overleden
Op 21 maart 2021 13:45:12 schreef Bavelt:
Voor de liefhebbers:Dit is uiteindelijk het project sterrenhemel geworden.
Het is geschreven in MikroBasic, met als processor de PIC16F18857.......
....Dank aan iedereen, in het bijzonder aan Arco, voor de bijdrage die ik kreeg om dit te maken.
Heb je er ook een filmpje van? dat zegt mij meer dan de ZIP-file
Special Member
Time-out moet je dan ook inbouwen in i2c_start/restart/stop/write/read, anders hangt de boel daar weer.
Ik zou ook eens naar het geheel kijken, want een time-out (hangen) op de i2c bus mag sowieso nooit voorkomen.
Golden Member
Op 7 april 2021 22:38:52 schreef Arco:
Time-out moet je dan ook inbouwen in i2c_start/restart/stop/write/read, anders hangt de boel daar weer.Ik zou ook eens naar het geheel kijken, want een time-out (hangen) op de i2c bus mag sowieso nooit voorkomen.
Je krijgt het als bv de SDA of SCL verbinding naar een device weg is (slechte dupont verbinding)
Golden Member
Op 7 april 2021 22:11:42 schreef Shiptronic:
[...]Heb je er ook een filmpje van? dat zegt mij meer dan de ZIP-file
Dit weekend is gepland om het defintief aan het plafond te monteren. Dan zal ik een filmpje maken.
Golden Member
Time-out moet je dan ook inbouwen in i2c_start/restart/stop/write/read, anders hangt de boel daar weer.
Klopt, daar was ik idd ook achter gekomen.
Je kunt ook niet simpel
pic basic code:
If (I2C1_Is_Idle)= 1
I2C1_Start()
I2C1_Wr(0x78)
I2C1_Wr(0x80)
I2C1_Wr(pCmd)
I2C1_Stop()
End IF
End Sub
Doen
Met een juiste bedrading is het probleem niet echt actueel. Maar het is wel iets om rekening mee te houden.
Special Member
Ik heb daar een eigen library voor gemaakt ('hangen' vind ik onacceptabel)
pic basic code:
module lib_i2c
Const I2CTimeOut = 200
Dim I2cStatus As Byte
'Statusbits: 00000001 - Start
' 00000010 - Restart
' 00000100 - Stop
' 00001000 - Write
' 00010000 - Read
' 00100000 - Idle
' 01000000 - Receive buffer
' 10000000 - Busy
Sub Procedure I2CInit()
Sub Procedure I2CStart()
Sub Procedure I2CRestart()
Sub Procedure I2CStop()
Sub Procedure I2CWrite(Dim pDat As Byte)
Sub Procedure I2CIdle()
Sub Function I2CRead(Dim pAck As Byte) As Byte
implements
'==================================================================================================
Sub Procedure I2CIdle() 'Wait for bus idle
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
For lCnt = 0 To I2CTimeout '
If (I2C1CON And 0x1F) = 0 then break end if '
Next lCnt '
I2cStatus.5 = (I2C1CON And 0x1F) '
End Sub '
'==================================================================================================
Sub Procedure I2Cinit() 'Init I2C1 peripheral (400kHz)
'--------------------------------------------------------------------------------------------------
I2C1BRG = 0x0025 '(Fcy/scl)-(Fcy/10000000) -1
I2CEN_Bit = 1 'Enable I2C1
Delay_ms(10) '
I2C1STAT = 0 '
End Sub '
'==================================================================================================
Sub Procedure I2CStart() 'Start bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2cStatus = 0x80
I2CIdle() 'Wait for bus idle
SEN_Bit = 1 'Set start bit
For lCnt = 0 To I2CTimeout 'Wait for bit to clear
If (SEN_Bit = 0) Then Break End If '
Next lCnt '
I2cStatus.0 = SEN_bit 'Errorstatus
End Sub '
'==================================================================================================
Sub Procedure I2CRestart() 'Restart bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
RSEN_Bit = 1 'Set repeated start bit
For lCnt = 0 To I2CTimeout 'Wait for bit to clear
If (RSEN_Bit = 0) Then Break End If '
Next lCnt '
I2cStatus.1 = RSEN_bit 'Errorstatus
End Sub '
'==================================================================================================
Sub Procedure I2CStop() 'Stop bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
PEN_Bit = 1 'Set stop bit
For lCnt = 0 To I2CTimeout 'Wait for bit to clear
If (PEN_Bit = 0) Then Break End If '
Next lCnt '
I2cStatus.2 = PEN_Bit 'Errorstatus
I2cStatus.7 = 0 '
End Sub '
'==================================================================================================
Sub Procedure I2CWrite(Dim pDat As Byte) 'Write byte pDat to bus
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
MI2C1IF_Bit = 0 'Clear interruptflag
I2C1TRN = pDat 'Data to send into buffer
For lCnt = 0 To I2CTimeout 'Wait for interruptflag to
If MI2C1IF_bit Then Break End If 'get set
Next lCnt '
I2cStatus.3 = MI2C1IF_Bit Xor 1 'Errorstatus
End Sub
'==================================================================================================
Sub Function I2CRead(Dim pAck As Byte) As Byte 'Read byte of bus(1=Nack/0=Ack)
'--------------------------------------------------------------------------------------------------
Dim lCnt As Word '
I2CIdle() 'Wait for bus idle
MI2C1IF_Bit = 0 'Clear interruptflag
RCEN_Bit = 1 '
For lCnt = 0 To I2cTimeout 'Wait for buffer
If RBF_Bit Then Break End If '
Next lCnt '
I2cStatus.6 = RBF_Bit Xor 1 'Errorstatus
Result = I2C1RCV 'Get received byte
ACKDT_Bit = pAck 'Send Ack/Nack
ACKEN_Bit = 1 '
For lCnt = 0 To I2CTimeout '
If MI2C1IF_Bit Then Break End If '
Next lCnt '
I2cStatus.4 = MI2C1IF_Bit Xor 1 'Errorstatus
End Sub '
end.
'==================================================================================================
Golden Member
Op 8 april 2021 22:40:29 schreef Arco:
Ik heb daar een eigen library voor gemaakt ('hangen' vind ik onacceptabel)pic basic code:
module lib_i2c Const I2CTimeOut = 200 Dim I2cStatus As Byte 'Statusbits: 00000001 - Start ' 00000010 - Restart ' 00000100 - Stop ' 00001000 - Write ' 00010000 - Read ' 00100000 - Idle ' 01000000 - Receive buffer ' 10000000 - Busy Sub Procedure I2CInit() Sub Procedure I2CStart() Sub Procedure I2CRestart() Sub Procedure I2CStop() Sub Procedure I2CWrite(Dim pDat As Byte) Sub Procedure I2CIdle() Sub Function I2CRead(Dim pAck As Byte) As Byte implements '================================================================================================== Sub Procedure I2CIdle() 'Wait for bus idle '-------------------------------------------------------------------------------------------------- Dim lCnt As Word ' For lCnt = 0 To I2CTimeout ' If (I2C1CON And 0x1F) = 0 then break end if ' Next lCnt ' I2cStatus.5 = (I2C1CON And 0x1F) ' End Sub ' '================================================================================================== Sub Procedure I2Cinit() 'Init I2C1 peripheral (400kHz) '-------------------------------------------------------------------------------------------------- I2C1BRG = 0x0025 '(Fcy/scl)-(Fcy/10000000) -1 I2CEN_Bit = 1 'Enable I2C1 Delay_ms(10) ' I2C1STAT = 0 ' End Sub ' '================================================================================================== Sub Procedure I2CStart() 'Start bus '-------------------------------------------------------------------------------------------------- Dim lCnt As Word ' I2cStatus = 0x80 I2CIdle() 'Wait for bus idle SEN_Bit = 1 'Set start bit For lCnt = 0 To I2CTimeout 'Wait for bit to clear If (SEN_Bit = 0) Then Break End If ' Next lCnt ' I2cStatus.0 = SEN_bit 'Errorstatus End Sub ' '================================================================================================== Sub Procedure I2CRestart() 'Restart bus '-------------------------------------------------------------------------------------------------- Dim lCnt As Word ' I2CIdle() 'Wait for bus idle RSEN_Bit = 1 'Set repeated start bit For lCnt = 0 To I2CTimeout 'Wait for bit to clear If (RSEN_Bit = 0) Then Break End If ' Next lCnt ' I2cStatus.1 = RSEN_bit 'Errorstatus End Sub ' '================================================================================================== Sub Procedure I2CStop() 'Stop bus '-------------------------------------------------------------------------------------------------- Dim lCnt As Word ' I2CIdle() 'Wait for bus idle PEN_Bit = 1 'Set stop bit For lCnt = 0 To I2CTimeout 'Wait for bit to clear If (PEN_Bit = 0) Then Break End If ' Next lCnt ' I2cStatus.2 = PEN_Bit 'Errorstatus I2cStatus.7 = 0 ' End Sub ' '================================================================================================== Sub Procedure I2CWrite(Dim pDat As Byte) 'Write byte pDat to bus '-------------------------------------------------------------------------------------------------- Dim lCnt As Word ' I2CIdle() 'Wait for bus idle MI2C1IF_Bit = 0 'Clear interruptflag I2C1TRN = pDat 'Data to send into buffer For lCnt = 0 To I2CTimeout 'Wait for interruptflag to If MI2C1IF_bit Then Break End If 'get set Next lCnt ' I2cStatus.3 = MI2C1IF_Bit Xor 1 'Errorstatus End Sub '================================================================================================== Sub Function I2CRead(Dim pAck As Byte) As Byte 'Read byte of bus(1=Nack/0=Ack) '-------------------------------------------------------------------------------------------------- Dim lCnt As Word ' I2CIdle() 'Wait for bus idle MI2C1IF_Bit = 0 'Clear interruptflag RCEN_Bit = 1 ' For lCnt = 0 To I2cTimeout 'Wait for buffer If RBF_Bit Then Break End If ' Next lCnt ' I2cStatus.6 = RBF_Bit Xor 1 'Errorstatus Result = I2C1RCV 'Get received byte ACKDT_Bit = pAck 'Send Ack/Nack ACKEN_Bit = 1 ' For lCnt = 0 To I2CTimeout ' If MI2C1IF_Bit Then Break End If ' Next lCnt ' I2cStatus.4 = MI2C1IF_Bit Xor 1 'Errorstatus End Sub ' end. '==================================================================================================
Dat ziet er inderdaad goed uit. Je gebruikt dus niet de standaard MikroBasic I2C library maar deze.
Je kunt dan dus bij elke uitvoering de status controleren en in je hoofdprogramma aangeven wat er dan moet gebeuren (bv foutmelding of verder gaan). Toch?
Ik zie hier het voor mij nieuwe Implements. Eerst som je de procedures op en vervolgens worden ze gespecificeerd.
Wat is nu het nut van deze implements?
Golden Member
Terecht zeg je dat 'hangen' niet acceptabel is. Je verliest daardoor de controle over je programma wanneer een device om wat voor reden ook niet goed reageert.
Zou het eigenlijk niet zo moeten zijn dat MB in zijn eigen library een error-afhandeling had moeten maken in zijn procedures?
Special Member
Heb ik al eens gevraagd.
Men zei dat ze expres voor deze oplossing hebben gekozen, omdat het voor minder gevorderde programmeurs anders misschien te ingewikkeld zou worden...
Implements is altijd noodzakelijk in een module. Er staat een stuk over modules in de helpfile...
Het 'hangen' gebeurt trouwens niet alleen bij fysieke busproblemen.
Sommige slaves hangen ook als je er teveel data naar toe stuurt zonder te wachten tot de bus weer vrij is...
[Bericht gewijzigd door Arco op vrijdag 9 april 2021 11:53:02 (25%)
Golden Member
De sterrenhemel zit aan het plafond, de print met processor (niet zichtbaar) tussen de panelen en plafond geprutst. Het werkt.
Maar heb toch nog wat problemen met stabiliteit (af en toe hangt het spul).
Wat ik zelf wat apart vind:
In de testopstelling op breadboard kan ik vanuit de laptop - USB de Pickit2 aansturen, die tevens de voeding verzorgt voor de schakeling, maar ook 8 LED matrixen met MAX7219 aangesloten. En een TSOP1836 IR-sensor ook aan boord. De ledjes branden keurig en de schakeling werkt.
Maar.., bij gebruik van de 'losse' leds i.p.v de matrix-LED's (1088AS), dan werkt de schakeling wel, echter de TSOP1836 IR sensor houdt het voor gezien
Die werkt alleen wanneer er een externe voeding van 5V is aangesloten.
Ik kan dat niet echt verklaren.
Zijn die Ledjes dan zo verschillend?
Golden Member
Ik had daarnaast nog een twijfelpuntje:
De processor PIC16F18857 wordt nu maximaal gebruikt:
8 MAX7219's aangestuurd met dus 512 leds via SPI
Een RTC DS 3231 via I2C
Dan 7 PWM's voor 5 Marsleds en twee maanhelften.
Nu vroeg ik me af of dit niet teveel gevraagd is van het ding.
Ik kan natuurlijk de Marsleds en Maan aansturen met een eigen processortje, bv de PIC 12F1572, die ook nog eens een 16-bits PWM heeft.
En daar een apart printje van maken.
Is dat een rare gedachte?
Special Member
Hij doet 't of hij doet het niet, 'teveel gevraagd' is er niet. (als alles qua timing erin past is het prima)
Enige wat ik controleer is meestal of er geen interrupts worden overgeslagen. (dat duidt er nl op dat er meer code is dan kan worden uitgevoerd)
Simpel te controleren door een outputpin iedere interrupt te togglen: er moet dan een nette 50/50 duty blokgolf uitkomen.
Als er soms blokken tussen zitten die langer zijn, dan is er een interrupt overgeslagen...
Golden Member
Qua interrupt is de timer de enige die ik gebruik in het programma.
Daar zitten alle tellers aan gekoppeld.
En er wordt gekeken of binnen de tijd een (geldig) IR-signaal is ontvangen.
Het blijkt dat de processor gedurende de nacht stopt. De ledjes houden dan wel hun status quo (vanuit de MAX7219) en branden weliswaar, maar er 'loopt' niks meer. Geen maan, mars, en geen IR-controle meer.
Dat is natuurlijk niet de bedoeling.
In mijn testopstelling op breadboard loopt alles gewoon door.
Het enige echte verschil zijn de kabels naar de LED-panels. Die zijn doorgelust, de maximale lengte is 4.80 meter.
Geldt hier nu ook voor ze doen het of niet? Of kan zo'n kabel de processor op een gegeven moment ook laten stressen?
Golden Member
Op 12 april 2021 12:02:47 schreef Arco:
Hij doet 't of hij doet het niet, 'teveel gevraagd' is er niet. (als alles qua timing erin past is het prima)
Enige wat ik controleer is meestal of er geen interrupts worden overgeslagen. (dat duidt er nl op dat er meer code is dan kan worden uitgevoerd)Simpel te controleren door een outputpin iedere interrupt te togglen: er moet dan een nette 50/50 duty blokgolf uitkomen.
Als er soms blokken tussen zitten die langer zijn, dan is er een interrupt overgeslagen...
Dit is de summary. Qua RAM en ROM zit het wel goed lijkt me...
Overleden
Lange kabels kunnen antennes worden! En voor de gekste problemen zorgen
Welk type kabel gebruik je? soms helpt het om (getwiste) netwerk kabel( sheilded) te gebruiken.
[Bericht gewijzigd door Shiptronic op maandag 12 april 2021 12:18:42 (40%)
Golden Member
Op 12 april 2021 12:16:35 schreef Shiptronic:
Lange kabels kunnen antennes worden! En voor de gekste problemen zorgenWelk type kabel gebruik je? soms helpt het om (getwiste) netwerk kabel( sheilded) te gebruiken.
Ik heb UTP kabel CAT 5 gebruikt
Golden Member
Op 12 april 2021 12:02:47 schreef Arco:
Hij doet 't of hij doet het niet, 'teveel gevraagd' is er niet. (als alles qua timing erin past is het prima)
Enige wat ik controleer is meestal of er geen interrupts worden overgeslagen. (dat duidt er nl op dat er meer code is dan kan worden uitgevoerd)Simpel te controleren door een outputpin iedere interrupt te togglen: er moet dan een nette 50/50 duty blokgolf uitkomen.
Als er soms blokken tussen zitten die langer zijn, dan is er een interrupt overgeslagen...
Ik heb voor de zekerheid een 'Toggle' ingebouwd.
Het plaatje levert wel een goede 50/50 blok op.
Maar wat opvalt: op de 'bovenkant' van het signaal zit redelijk veel ruis / rommel.
Uitvergroot:
Dit topic is gesloten