Met mijn arduino kwam ik een keer het volgende programma tegen
een delay lose knipper led.

nou vroeg ik mij af of zoiets ook mogelijk is met PIC (picbasic). Ik heb hier al een poos naar gezocht, maar tot nu toe niks gevonden.

MVG Ruben

Arduino Code

/* Blink without Delay
 
 Turns on and off a light emitting diode(LED) connected to a digital  
 pin, without using the delay() function.  This means that other code
 can run at the same time without being interrupted by the LED code.
 
 The circuit:
 * LED attached from pin 13 to ground.
 * Note: on most Arduinos, there is already an LED on the board
 that's attached to pin 13, so no hardware is needed for this example.
 
 
 created 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 
 This example code is in the public domain.

 
 http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
 */

// constants won't change. Used here to
// set pin numbers:
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;  

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

Het enige wat ze hier doen is een counter maken, en als de counter een bepaalde waarde heeft de led-pin weer omschakelen.

Kun je toch zo omzetten naar (pic)-basic....

Roche

En anders gebruik je de interrupt timer ;)

ligt een beetje aan welke pic je voor ogen hebt.

maar meestal is dit nou net niet de bedoeling omdat je anders precies kunt zien als er iets fout gaat met de code want de led knippert niet meer.

[Bericht gewijzigd door roel999 op (61%)]

Zoiets?


Device 16F628A


Symbol Wacht1 = 100
Dim Wacht2 As Word

Symbol Led = PORTB.0
TRISB.0 = 0

Main:

    DelayMS 1

    Inc Wacht2
    If Wacht2 > Wacht1 Then
        Toggle Led
        Wacht2 = 0
    EndIf
GoTo Main

TS wil een DELAY-loze knipperled, dus dat zal niet helemaal de bedoeling zijn volgens mij...

Op 10 oktober 2011 21:48:15 schreef Arco:
TS wil een DELAY-loze knipperled, dus dat zal niet helemaal de bedoeling zijn volgens mij...

Nou dat laat hij de delay toch weg, alleen zal de MC wel heel snel aan de 100 zijn!

Het is natuurlijk een beetje afhankelijk hoe het verdere programma
eruit gaat zien (vertraging door programma gebeurtenissen) en de
gebruikte klok snelheid.

Waarom zou je een interrupt inzetten voor een toggle?

@TS: waarom wil je een delay-loze knipperled? Oftewel, wat is er tegen een knipperled met delays?
Verder ben ik het helemaal eens met het antwoord van Fredjuhh, gebruik een timer interrupt.

gewoon zorgen dat de pic tussen while en wend lang genoeg bezig is >:)


while 1 = 1

led = 1

; iets dat lang duurt

led = 0
wend
end

haha :)

nee volgens mij zijn daar timers voor
maar welke erin zitten verschilt per pic
ben hier overigens nog niet mee bezig geweest...

Laat nu eerst de TS maar eens antwoorden waarom hij geen delay wil gebruiken en waar het voor is.

't zal toch niet weer "classified" zijn...

Roche

Op 10 oktober 2011 22:18:50 schreef roel999:
gewoon zorgen dat de pic tussen while en wend lang genoeg bezig is >:)


while 1 = 1

led = 1

; iets dat lang duurt

led = 0
wend
end

Voorbeeld gaat niet werken!

Led gaat aan en blijft lang aan en gaat heel heel
kort uit om dan weer lang aan te gaan!

ha sh*t dat heb je goed gezien.

meestal kom ik pas tijdens het debuggen met werkende installatie achter dit soort foutjes.

hier een nieuwe:


while 1 = 1

led = 1

;iets dat lang duurt

led = 0 
; iets dat lang of enige tijd duurt
wend
end

zo is die code niet echt zinvol maarja

EDIT:
ah ik heb wat gevonden voor als je de "16f628A" gebruikt.

er zit een timer in en je moet je jouw code de waarde van die timer scannen, als die een bepaalde waarde heeft bereikt toggle je de led en clear je de waarde waardoor de teller opnieuw moet beginnen.

en in de tussentijd kun je wat anders doen...

info in http://ww1.microchip.com/downloads/en/DeviceDoc/40044F.pdf

[Bericht gewijzigd door roel999 op (40%)]

Op 10 oktober 2011 22:22:37 schreef Roches:
Laat nu eerst de TS maar eens antwoorden waarom hij geen delay wil gebruiken en waar het voor is.

Roche

Simpel, omdat je in een wait/delay niets anders kunt doen, dus je kunt beter met een counter oid werken.

Op 10 oktober 2011 22:39:43 schreef roel999:
ha sh*t dat heb je goed gezien.

meestal kom ik pas tijdens het debuggen met werkende installatie achter dit soort foutjes.

hier een nieuwe:


while 1 = 1

led = 1

;iets dat lang duurt

led = 0 
; iets dat lang of enige tijd duurt
wend
end

niet echt zinvol maarja

Daarom kan je beter toggelen!


while 1 = 1

   ;Programma Main Loop

   Toggle Led 
wend

ja dat kan, is eigenlijk wel makkelijker.
maar als ik daar eenmaal weer aan begin...

tsja ik heb toch geen code limiet,

[Bericht gewijzigd door roel999 op (30%)]

sorry voor mijn late reactie, maar ik lag gister de hele dag op bed!

er zit een timer in en je moet je jouw code de waarde van die timer scannen, als die een bepaalde waarde heeft bereikt toggle je de led en clear je de waarde waardoor de teller opnieuw moet beginnen.

Precies wat ik bedoel! Ik zal de datasheet eens even bestuderen.

Of gewoon een interrupt op de timer zetten en daarin de LED toggelen. Dan hoef je verder in je 'main' code helemaal niets meer te doen.

ah ik heb wat gevonden voor als je de "16f628A" gebruikt. ...er zit een timer in

Sterker nog: er zitten er zelfs 3 in... ;)


Device 16F77                                       ;Een 16F77 type
Config HS_OSC, WDT_OFF, PWRTE_ON           ;HS_OSC, CP_OFF, WDT_OFF, PWRTE_ON, LVP_OFF, BODEN_OFF, DEBUG_OFF, MCLRE_OFF
ALL_DIGITAL TRUE 
XTAL 20 

HSERIAL_BAUD = 9600        ' baud rate is 19200
HSERIAL_RCSTA = %10010000  ' laat de USART voortdurend ontvangen
HSERIAL_TXSTA = %00100000  ' zorgt dat de USART kan verzenden 
HSERIAL_CLEAR = On 

ON_Interrupt GoTo ICR

SYMBOL RBIF = INTCON.0 ' RB Port Interrupt Flag
SYMBOL INTF = INTCON.1 ' RB0 External Interrupt Flag
SYMBOL T0IF = INTCON.2 ' TMR0 Overflow Interrupt Flag
SYMBOL RBIE = INTCON.3 ' RB Port Change Interrupt Enable
SYMBOL INTE = INTCON.4 ' RB0 External Interrupt Enable
SYMBOL T0IE = INTCON.5 ' TMR0 Overflow Interrupt Enable
SYMBOL PEIE = INTCON.6 ' Peripheral Interrupt Enable
SYMBOL GIE = INTCON.7  ' Global Interrupt Enable
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
SYMBOL T0SE = OPTION_REG.4     ' TMR0 Source Edge Select
SYMBOL T0CS = OPTION_REG.5     ' TMR0 Clock Source Select
SYMBOL INTEDG = OPTION_REG.6   ' Interrupt Edge Select
SYMBOL NOT_RBPU = OPTION_REG.7 ' PORTB Pull-up Enable

clear

set ps0
set ps1
set ps2
clear PSA

main:


clear GIE
TMR0 = 64
T0CS = 0
T0if = 0
t0ie = 1
GIE = 1


While 1=1
; hoofdprogramma

Wend

ICR:


TMR0 = 64
T0if = 0 

inc TIMER

Context Restore 


end

Even snel een stuk code geplakt uit mijn laatste project.
Wat er gebeurd: Bij opstarten wordt de timer ingesteld. Ik weet de technische onderbouwing niet meer maar TMR0 = 64 staat voor de timer instellen op 10ms. Als deze afegelopen is komt er een interrupt (T0IF wordt dan 1) en daarmee verhoog je een waarde. in het programma controleer je gewoon of een getal groter is dan die waarde.

Op 10 oktober 2011 22:41:17 schreef Sine:
[...]

Simpel, omdat je in een wait/delay niets anders kunt doen, dus je kunt beter met een counter oid werken.

Dat weet ik natuurlijk ook wel, maar TS geeft nog steeds niet aan wat hij wil gaan doen en waar hij specifiek de delay-loze code voor wil gaan gebruiken.

Zolang TS niet duidelijk is zal er verder ook geen to-the-point reactie komen.

Met een timer-interrupt is het natuurlijk zo opgelost....

Die loop-constructie in de Arduino code is ook wel te realiseren op een PIC-controller.

Het enige probleem is de millis()-functie. Die telt waarschijnlijk het aantal millisecondes die sinds power-up zijn verlopen.

Als het alleen gaat om het vaststellen dat er weer een milliseconde is verlopen, kun je dat oplossen door een timer in te stellen die iedere milliseconde overloopt. Een interrupt is niet nodig.

In de loop wordt iedere keer gecontroleerd of de timer is overgelopen. Zo ja, overflow-flag wissen en de getimede actie uitvoeren.

@roches
Ik heb geen specefiek project waarbij ik dit nodig heb. Ik heb nog niet zoveel kaas gegeten met PIC. dus deze vraag was gewoon informatief bedoelt. Wat ik bijvoorbeeld hiermee wil berijken, is dat ik een hoofd programma kan draaien. met daarnaast 4 gemultiplexte 7segment displays die bijv. elke 5ms geupdate moeten worden.

@Electronick
Interesant, Ik zal jouw programma eens proberen.