attachInterrupt() Not Working arduino nano Please help

hello i'm making machine with encoder .I have a problem probably with AttachInterupt() because if i run this machine on this cycle (+10000steps-10000steps) it's run perfectly and if i run machine on this cycle (+10000steps ,60s of break, - 10000steps ) for +10000 steps its work perfectly and if break is done there is some problem like sleeping(?) or reaction delay(?) thats machine counts from zero i don't know what is it :frowning: ? this is my code:

// Autor: Mariusz i Stanisław Kaczmarek 
#include <SD.h>
int SD_WRITE = 0;
File myFile;
#define PIN_SPI_CS 4
#include <ArrayList.h>

int save_done =0;
long cdk = 0;
volatile long encoderPosition = 0;
int continue321 = 1;
int encoderPinA = 2;
int encoderPinB = 3;
int lastEncoded = 0;  
int przycisk = 0;
int continue123 = 0;
int przerwa = 0;
int opi = 0;
int myList[70] = {};
int myList2[70] = {};
long przerwa2 = 0;
#include <SPI.h>
#include <List.hpp>
#include <stdlib.h>

//List<int> myList; 
//List<int> myList2; 
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 4;

void setup() {

Serial.begin(2000000);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

 
 if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    digitalWrite(5 , HIGH);
    while (1);
  }


attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE);
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);

pinMode(A1 , INPUT);
pinMode(9, INPUT_PULLUP);
pinMode(5 , OUTPUT);
delay(1000);
digitalWrite(5 , LOW);

}





void loop() {
if (SD_WRITE == 1 && save_done ==0 ){
  myFile = SD.open("test.txt", FILE_WRITE);
  if (myFile) {
  myFile.println("NEXT_TEST:");
  detachInterrupt(digitalPinToInterrupt(2));
  detachInterrupt(digitalPinToInterrupt(3));
  Serial.println("Zapisywanie do karty sd...");
  for (int i = 0; i <= 70; i++) {
      Serial.println(myList[i]);
      myFile.println(myList2[i]);
      Serial.println(myList2[i]);
      myFile.println(myList[i]);
  }
  digitalWrite(5 , HIGH);
  myFile.close();
  }
  else{
    Serial.println("error opening test.txt");
  }

save_done = 1;
}
	if (digitalRead(9) == LOW && przycisk == 0){
		Serial.println("START");
		encoderPosition = 0;
		przycisk = 1;
		Serial.println(encoderPosition);
    Serial.println(continue123);
    Serial.println(przycisk);
    
	}

  
  

	if (przycisk == 1 &&  (millis() - przerwa )>= 1000){
		myList[cdk] = (analogRead(A1)/20.46);
		myList2[cdk] = (encoderPosition);
		przerwa = millis();
    cdk++;
	}
  


}

void updateEncoder() {
  int MSB = digitalRead(encoderPinA); // Most significant bit
  int LSB = digitalRead(encoderPinB); // Least significant bit

  int encoded = (MSB << 1) | LSB; // Converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; // Adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderPosition --;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderPosition ++;

  lastEncoded = encoded; // Store this value for next time
  Serial.println(encoderPosition);
  //Serial.println(encoderPosition);
  if (encoderPosition >= 9000 && continue123 == 0 && przycisk == 1 ){
    encoderPosition = 9000;
		Serial.println("ENCODER_POSTION9000");
    
    continue123 = 1;
    digitalWrite(5 , HIGH);
	
		
  }
  if (encoderPosition <= 0 && continue123 == 1  ){
    encoderPosition = 0;
		Serial.println("ENCODER_POSTION0");
		digitalWrite(5 , LOW);
    
		przycisk = 0;
		continue123 =0;
    SD_WRITE = 1;
  
	}
    


}

put your code between CODE tags

1 Like

is it really work?

yes :slight_smile:

#include <SD.h>
#include <ArrayList.h>
#include <SPI.h>
#include <List.hpp>
#include <stdlib.h>
File myFile;
#define PIN_SPI_CS 4
int encoderPinA = 2;
int encoderPinB = 3;

int SD_WRITE = 0;
int save_done = 0;
long cdk = 0;
volatile long encoderPosition = 0;
volatile int continue321 = 1;
volatile int przycisk = 0;
volatile int continue123 = 0;

int lastEncoded = 0;
int opi = 0;
int myList[70] = {};
int myList2[70] = {};
int przerwa = 0;
long przerwa2 = 0;

//List<int> myList;
//List<int> myList2;

Sd2Card card;
SdVolume volume;
SdFile root;

void setup() {
  Serial.begin(2000000);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  if (!SD.begin(PIN_SPI_CS)) {
    Serial.println("initialization failed!");
    digitalWrite(5 , HIGH);
    while (1);
  }
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(A1 , INPUT);
  pinMode(9, INPUT_PULLUP);
  pinMode(5 , OUTPUT);
  delay(1000);
  digitalWrite(5 , LOW);
  attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
}

void loop() {
  if (SD_WRITE == 1 && save_done == 0 ) {
    detachInterrupt(digitalPinToInterrupt(2));
    myFile = SD.open("test.txt", FILE_WRITE);
    if (myFile) {
      myFile.println("NEXT_TEST:");
      Serial.println("Zapisywanie do karty sd...");
      for (int i = 0; i <= 70; i++) {
        Serial.println(myList[i]);
        myFile.println(myList2[i]);
        Serial.println(myList2[i]);
        myFile.println(myList[i]);
      }
      digitalWrite(5 , HIGH);
      myFile.close();
    }
    else Serial.println("error opening test.txt");
    save_done = 1;
    attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
  }
  if (digitalRead(9) == LOW && przycisk == 0) {
    Serial.println("START");
    encoderPosition = 0;
    przycisk = 1;
    Serial.println(encoderPosition);
    Serial.println(continue123);
    Serial.println(przycisk);
  }
  if (przycisk == 1 &&  (millis() - przerwa ) >= 1000) {
    myList[cdk] = (analogRead(A1) / 20.46);
    myList2[cdk] = (encoderPosition);
    przerwa = millis();
    cdk++;
  }
}

void updateEncoder() {
  if (digitalRead(encoderPinA) == digitalRead(encoderPinB)) {if(encoderPosition)encoderPosition --;}
  else {if(encoderPosition<9000)encoderPosition ++;}

  if (encoderPosition >= 9000 && continue123 == 0 && przycisk == 1 ) {
    encoderPosition = 9000;
    Serial.println("ENCODER_POSTION9000");
    continue123 = 1;
    digitalWrite(5 , HIGH);
  }

  if (encoderPosition <= 0 && continue123 == 1  ) {
    encoderPosition = 0;
    Serial.println("ENCODER_POSTION0");
    digitalWrite(5 , LOW);
    przycisk = 0;
    continue123 = 0;
    SD_WRITE = 1;
  }
}

sorry but that is not reading any information of encoder. is attachinterupt() sleeping ?

do you think if you not see spamming message in serial monitor that is only because encoder sleeping? no, it is not.

no I don't see the message from the encoder for a while, as if the Arduino had a delayed reaction and the Enkoderpositoin starts counting from zero, not from 9000

yes, exactly how your code it want.

what I meant was that after a 60-second break it starts from 0, not from 9000

Detaching then reattaching the interrupt in loop() is just wrong. If you must suspend interrupt processing, use a (volatile) flag in the ISR to simply return. Update that flag when you want to start processing again.

But, why do you think you need to suspend interrupt processing in the first place?

sorry, i see in code no break

Your code's logic is pretty convoluted and and your explanation is unclear. Please take another shot at clearly explaining what you're trying to do.

1 Like

thank you very much, but how another sketch help me to understand about

show pictures of your setup, may be it bring more clue

I'm trying something like a tonometer or an indentation device - this thing is supposed to rotate 9000 degrees in the extended motor, wait 60 seconds and then withdraw also by 9000 degrees and at the same time save the results on the SD card from the force sensor and encoder and display messages in Polish on the display. To make this project I used 2 Arduino Nanos - if it's a question of performance, I can replace the Arduino Nano with an Arduino Portenta H7

and why it is splitted into two devices?

  while(digitalRead(3) == LOW) { 
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(312); 
      digitalWrite(stepPin, LOW);
      delayMicroseconds(312); 
    }

    Serial.println(millis() - mini);
    mini = millis();
    digitalWrite(dirPin, LOW);
    delay(60000);// 60 s break
    while(digitalRead(3) == HIGH){

      digitalWrite(stepPin, HIGH);
      delayMicroseconds(312);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(312); 

    }

I will show you pictures of my setup in 5 min :slight_smile:

So your encoder has 1-degree / step resolution?

Yes

The #1 code has a lot of printing in the interrupt (move those into loop) and uses lots of non-volatile ints to communicate one-bit flags with loop (make those volatile bytes).

I think it is intended as a one-shot file write and you need to re-cycle the power to do a new write cycle.