Sida 1 av 2

Problem med interupt Uno32

Postat: 31 mars 2024, 17:47:02
av SeniorLemuren
Jag vill köra en stegmotor med AccelStepper och samtidigt räkna pulser från en optogivare. Jag använder en chipKit Uno32 till detta. Jag har gjort ett program som använder Accelstepper för att köra stegmotorn och samtidigt använder jag en interupt pinne för att ta in pulserna. I programmet blinkar jag en led för att se att pulser kommer in,

Avbrottsrutinen fungerar inte så länge motorn snurrar

Kod: Markera allt

stepper.runToNewPosition(20000);
När den stoppar så fungerar avbrottsrutinen. Vad gör jag för fel?

Kod: Markera allt

volatile boolean LEDstate = false; // To make sure variables shared between an ISR
//the main program are updated correctly,declare them as volatile.

#include <AccelStepper.h>
#define dirPin 3
#define stepPin 4

#define motorInterfaceType 1

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

void setup() {
stepper.setMaxSpeed(5000);
stepper.setAcceleration(1000);

pinMode(PIN_LED1, OUTPUT); //set pin 13 as output
attachInterrupt(3, LEDchange, FALLING); // avbrottsrutin 3 på pinne 7
}

void loop() {
digitalWrite(PIN_LED1, LEDstate); //pin 13 equal the state value 

stepper.runToNewPosition(20000);
}

void LEDchange() { 
  // ISR function
   LEDstate = !LEDstate; //toggle the state when the interrupt occurs
}

Re: Problem med interupt Uno32

Postat: 31 mars 2024, 19:49:09
av ToPNoTCH
Kollar man i dokumentationen finnar man:
Moves the motor (with acceleration/deceleration) to the new target position and blocks until it is at position. Dont use this in event loops, since it blocks.
Om du kör
run()
i main loopen istället borde det funka.

Du måste du givetvis sätta targetPosition() till 20000 (i ditt fall) i void setup.

Re: Problem med interupt Uno32

Postat: 31 mars 2024, 20:45:46
av SeniorLemuren
Kannon. Nu funkar det. :tumupp:

Re: Problem med interupt Uno32

Postat: 31 mars 2024, 22:02:21
av Klas-Kenny
Grejen är inte att interruptet inte körs.
Grejen är att interruptet uppdaterar LEDstate, men det ändrar inte utgången förrän nästa varv i loopen (nästa digitalWrite() ).

Flytta digitalWrite() till att köras ifrån interruptet så ska du se att det fungerar oavsett vad du gör i loop().

Re: Problem med interupt Uno32

Postat: 1 april 2024, 00:20:53
av SeniorLemuren
Ok. Men jag vill ju inte låsa loopen, ska göra lite mer i den, så jag kör så här nu och det funkar bra.

Kod: Markera allt

volatile boolean LEDstate = false; // To make sure variables shared between an ISR
//the main program are updated correctly,declare them as volatile.

#include <AccelStepper.h>
#define dirPin 3
#define stepPin 4

#define motorInterfaceType 1

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

void setup() {
stepper.setMaxSpeed(5000);
stepper.setAcceleration(1000);
stepper.moveTo(10000000);

pinMode(PIN_LED1, OUTPUT); //set pin 13 as output

attachInterrupt(3, LEDchange, FALLING);
}

void loop() {
digitalWrite(PIN_LED1, LEDstate); //pin 13 equal the state value 

stepper.run();
}

void LEDchange() { 
  // ISR function
   LEDstate = !LEDstate; //toggle the state when the interrupt occurs
}

Re: Problem med interupt Uno32

Postat: 1 april 2024, 01:21:57
av hawkan
Det råkar fungera. Klas-Kennys inlägg ska tas seriöst.
Släng bort LEDState. Utgången vet själv sitt tillstånd. Byt ut din Isr till

Kod: Markera allt

void LEDchange() { 
  // ISR function
  digitalWrite(PIN_LED1, !digitalRead(PIN_LED1));
}

Re: Problem med interupt Uno32

Postat: 1 april 2024, 08:37:15
av agehall
Nu är ju det stora misstaget att använda Arduino’s SW-platform, men att flytta DigitalWrite() till en ISR gör inte saken bättre. Det är helt rätt att göra så lite som möjligt i en ISR och sedan göra det tunga jobbet utanför.

Re: Problem med interupt Uno32

Postat: 1 april 2024, 08:54:21
av Klas-Kenny
Vad som är "rätt" och vad som är "fel" beror ju helt på applikationen.

Är det viktigt att utgången sätta "direkt", gör det ifrån interruptet. Sätts den tillräckligt snabbt även om man behöver vänta upp till ett helt varv i loopen, så har det sina fördelar att skriva därifrån. Och hur mycket som är okej att göra ifrån ett interrupt beror ju också helt på applikationen, hur länge det tål att uppehållas.
Att sätta en utgång är till 99.9% inte för mycket, med rimligt effektiv kod (vet inte hur effektivt digitalWrite är implementerat) så tar det inte mycket längre tid än att bara skriva en variabel.


Jag ville mest beskriva VARFÖR det inte fungerade först, och varför Run() fungerar. Förklaringen att runToNewPosition() är blockerande är bara en del av sanningen. Den blockerar nämligen inte några interrupt, som TS tycktes tro var det som hände.
Viktigt skillnad.

Re: Problem med interupt Uno32

Postat: 1 april 2024, 09:47:39
av hawkan
Att läsa och skriva en pinne är knappast för mycket i en isr, det är istället mycket lämpligt i detta fallet.
Det gör led-blinkandet helt fristående från applikationen och TS kan gå tillbaka till att positionera stegmotorerna
utan att strössla koden med digitalWritear. Leden blinkar när den ska.

Re: Problem med interupt Uno32

Postat: 1 april 2024, 10:59:36
av SeniorLemuren
Att blinka dioden är inte det huvudsakliga. Det var bara en test för att se om den skiva jag använder har tillräckligt stora slitsar för att generera stabila pulser.

Funktionen av det hela skall vara att ta emot pulser från 2 stegmotorer och kontrollera att de får samma antal pulser hela tiden. Detta är en alternativ lösning till det som diskuterades i tråden om att använda closed loop drivers till Y-motorerna på CNC-fräsen för att få stopp om den ena motorn kommer efter.

Så det saknas en hel del i programmet och som någon tidigare påpekade så strävar jag efter att lägga så lite som möjligt i avbrottsrutinen.

Re: Problem med interupt Uno32

Postat: 1 april 2024, 11:04:12
av SeniorLemuren
agehall skrev: 1 april 2024, 08:37:15 Nu är ju det stora misstaget att använda Arduino’s SW-platform, men att flytta DigitalWrite() till en ISR gör inte saken bättre. Det är helt rätt att göra så lite som möjligt i en ISR och sedan göra det tunga jobbet utanför.
Vilken plattform använder du till Digilent ChipKit Uno32?

Re: Problem med interupt Uno32

Postat: 1 april 2024, 11:11:17
av SeniorLemuren
ToPNoTCH skrev: 31 mars 2024, 19:49:09 Kollar man i dokumentationen finnar man:
Moves the motor (with acceleration/deceleration) to the new target position and blocks until it is at position. Dont use this in event loops, since it blocks.
Om du kör
run()
i main loopen istället borde det funka.

Du måste du givetvis sätta targetPosition() till 20000 (i ditt fall) i void setup.
Har du en länk till vilken dokumentation du fann denna information. Jag letar nämligen efter varför CHANGE i interruptrutinen inte fungerar. RISING och FALLING är inga problem.

Re: Problem med interupt Uno32

Postat: 1 april 2024, 11:16:59
av Klas-Kenny
All dokumentation finns här:
https://www.arduino.cc/reference/en/

Just det för AccelStepper finns här:
https://www.arduino.cc/reference/en/lib ... elstepper/
Letar man sig vidare där kommer man till sist hit:
https://www.airspayce.com/mikem/arduino ... e39a6f0e67

Re: Problem med interupt Uno32

Postat: 1 april 2024, 13:15:10
av SeniorLemuren
Tack. Men problemet är att jag inte använder Arduino utan chipKIT Digilent UNO32 som skiljer en hel del från Arduino
Microchip® PIC32MX320F128H microcontroller (80 Mhz 32-bit MIPS, 128K Flash, 16K SRAM) Det är interruptpinnarna jag vill veta mer om. Jag letar efter varför CHANGE i interruptrutinen inte fungerar. RISING och FALLING är inga problem. Kan ju tänkas vara skillnader där jämfört med Arduino

Re: Problem med interupt Uno32

Postat: 1 april 2024, 14:06:06
av Klas-Kenny
Då är du på lite smått hal is vad gäller dokumentation och allmänt stöd för vissa "specialgrejer".

Hittade källkoden,
https://github.com/chipKIT32/chipKIT-co ... upts.c#L71

Verkar som att man bara implementerat pin-interrupt via de specifika interrupt-pinnarna, som jag inte tror har stöd för interrupt-on-change utan bara vid antingen uppåtgående, eller nedåtgående flank. (Koden som sätter upp interruptet kollar till och med uttryckligen att mode != CHANGE, annars hoppar den över alltihop)
Hårdvaran stödjer "change notification" som kan ge interrupt vid godtycklig förändring på de flesta I/O, men det ger ett enda interrupt som man sen själv får kontrollera vilken av pinnarna som orsakade det. Osäker på hur man implementerar godtyckliga interrupt i Arduino-världen, men det går säkert googla sig till ifall man vill gå den vägen.