Interrupts

Can I interrupt a 'for' loop in 'void loop' from input from my rotary encoder?

Cause after the 'for' loop has finished the interrupt can initialize, but not while the 'for' loop is running.

I thought adding 'attachinterrupt' in the 'for' loop would help but apparently not.

Eurotrax: Can I interrupt a 'for' loop in 'void loop' from input from my rotary encoder?

Yes.

How?

If the appropriate interrupts are enabled, and you have an interrupt service routine, interrupts happen automatically whenever the interrupt condition is met.

Well currently if i rotate the rotary encoder during the 'for' loop it won't initialize the interrupt code until the 'for' loop is over.

This is the interrupt function i have:

void motorStop()
{
  //delay(4);
  if ((digitalRead(PinCLK)) || (!digitalRead(PinCLK)))
  rotate = digitalRead(PinDT); 
  turnDetected = true; //turn as according to rotary encoder 
}

And this is the code in my 'void loop' for text output from the interrupt:

if (turnDetected)
    {   
     while ((digitalRead(PinSW)) == HIGH) //wait for button press
     {
       lcd.setCursor(0,0);
       lcd.print("Stop tracking?");
   
       if ((digitalRead(PinSW)) == LOW)  //if button pressed stop tracking
       {
         lcd.clear();
         lcd.setCursor(0,0);
         lcd.print("Tracking stopped:");
         lcd.setCursor(0,2);
         lcd.print("Storing tracker...");
         delay(2000);
         break;
      }
    }
    lcd.clear();
    }
    turnDetected = false;

not seeing the point of

if ((digitalRead(PinCLK)) || (!digitalRead(PinCLK)))

won’t that always be TRUE
do you really mean

void motorStop()
{
  //delay(4);
  if ((digitalRead(PinCLK)) || (!digitalRead(PinCLK))){
  rotate = digitalRead(PinDT); 
  turnDetected = true; //turn as according to rotary encoder 
}}

if you need to read the pin to clear the int on change status, why not

void motorStop()
{

digitalRead(PinCLK);
rotate = digitalRead(PinDT);
turnDetected = true; //turn as according to rotary encoder
}

I can't see a "for" loop. Post your code.

There are two possible approaches.

If you know how to use Arduino interrupts they can be used to update a counter even while something else is happening.

Alternatively, don't use a FOR loop - which blocks until it finishes. Use code something like this

void loop() {
  // do stuff that would be in the FOR loop
  loopCounter++;
  if (loopCounter >= loopLimit) {
      // this marks the end of the FOR code
   }
  readEncoder();
}

which interleaves the FOR actions ste by step with the encoder reading

...R

i replaced the two main ‘for’ loops with the method instead of using millis for counting for how long to display a screen for. However now when it displays the screens i have made it flickers all the text and the text fades from bright to dark left to right on my LCD. Anyone know why?

/**************************Previous Versions*************************************/
//version 0.5 adds temp and time to tracking wait screen
//version 0.6 started implementation for interrupt
//version 0.7 removed for loops so interrupt can interrupt all code

/**************************Future features**************************************/
//implement stepper motor
//stop tracking so stop motor
//store tracker back to origianl state

#include "DHT.h"
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
#include <Time.h>
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 20 chars and 4 line display

//Temp sensor variables
#define DHTPIN 4     // what pin we're connected to
#define DHTTYPE DHT11   //DHT11
float temp_1, temp_2, hum_1, hum_2; 
int temp_max, temp_min;
int hum_max, hum_min;

//RTC variables
DHT dht(DHTPIN,DHTTYPE); 
RTC_DS1307 rtc;

//Rotary encoder variables
int PinSW = 7;  //SW pin on encoder connected to pin 7 
int PinCLK = 0; //generating interrupts using CLK signal //pin 2 but 0 for interrupt
int PinDT = 3; //reading DT signal
volatile boolean turnDetected;
volatile boolean rotate;

//other variables
unsigned long previousMillis = 0;
const long interval_1 = 5000;
const long interval_2 = 15000;



void setup(void)
{
  lcd.init(); 
  lcd.backlight();   
  dht.begin();
  Wire.begin();
  rtc.begin(); 
  
  pinMode(PinSW, INPUT); //set pin 7 for rotary encoder button
  pinMode(PinCLK, INPUT);
  pinMode(PinDT, INPUT);
  digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
  attachInterrupt (PinCLK, motorStop, FALLING); //
  
  lcd.setCursor(0,0);    
  lcd.print("Reading temp sensor:"); //first output reading sensor
  lcd.setCursor(0,1);
  lcd.print("Reading time module:"); //output reading time module
  lcd.setCursor(0,3);
  lcd.print("Version 0.7");
  
  temp_1 = dht.readTemperature();
  hum_1 = dht.readHumidity();
  delay(2000);
  lcd.clear();
  
  if (!rtc.isrunning()) 
  {
    Serial.println("RTC is NOT running!"); //second test RTC    
  }
  
  //*************************************** TIME SET *********************************************
  //only run following code once to set current date and time
  //rtc.adjust(DateTime(2015,5,05,18,39,00));  
  
  temp_min = temp_1; //initiazlize all min/max to first reading
  temp_max = temp_1;
  hum_min = hum_1;
  hum_max = hum_1;    
  
  
 //Rotary encoder push button start  
 while ((digitalRead(PinSW)) == HIGH)
 {
   DateTime now = rtc.now(); //get date and time
   lcd.setCursor(0,0);
   lcd.print("Start Tracking?");
   lcd.setCursor(0,2);
   lcd.print("Temperature: "); 
   lcd.print(temp_1);
   lcd.print((char)223);
   
   lcd.setCursor(0,3);
   int print_month = now.month();
    
    switch(print_month) //output current month
    {            
      case 1: 
      lcd.print("Jan");
      break;
      
      case 2:
      lcd.print("Feb");
      break;
      
      case 3:
      lcd.print("Mar");
      break;
      
      case 4:
      lcd.print("Apr");
      break;
      
      case 5:
      lcd.print("May");
      break;
      
      case 6:
      lcd.print("Jun");
      break;
      
      case 7:
      lcd.print("Jul");
      break;
      
      case 8:
      lcd.print("Aug");
      break;
      
      case 9:
      lcd.print("Sep");
      break;
      
      case 10:
      lcd.print("Oct");
      break;
      
      case 11:
      lcd.print("Nov");
      break;
      
      case 12:
      lcd.print("Dec");
      break;      
    }      
    
    lcd.print('/');
    lcd.print(now.day(), DEC);
    
    lcd.setCursor(10,3);
    //DETERMINE AM/PM
    int hour_24, hour_12;     
    hour_24 = now.hour();
    
    if (hour_24 == 0) //output changing 24AM to 12AM       
    hour_12 = 12;     
    
    else  //outputing 1-11PM/AM       
    hour_12 = (hour_24 % 12);    
    
    lcd.print(hour_12, DEC);
    lcd.print(':');
    
    if(now.minute() < 10)    
    lcd.print("0");     
    
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    
    if(now.second() < 10)    
    lcd.print("0");   
    
    lcd.print(now.second(), DEC);
    
    if(hour_24 < 12)
    lcd.print("AM");
    
    else
    lcd.print("PM");   

    temp_1 = dht.readTemperature();    
    
    
   if ((digitalRead(PinSW)) == LOW)
   {
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print("Tracking started:");
     delay(2000);
     break;
   }
 }
 lcd.clear();
}



void motorStop() //interrupt function 
{
  digitalRead(PinCLK); //check for rotation in rotary encoder
  rotate = digitalRead(PinDT); 
  turnDetected = true; //turn as according to rotary encoder   
}

second part to all of my code

void loop()
{ 
  unsigned long currentMillis = millis(); //initialize millis for screen switching
  
    if (turnDetected)
    {   
     while ((digitalRead(PinSW)) == HIGH) //wait for button press
     {
       lcd.setCursor(0,0);
       lcd.print("Stop tracking?");
   
       if ((digitalRead(PinSW)) == LOW)  //if button pressed stop tracking
       {
         lcd.clear();
         lcd.setCursor(0,0);
         lcd.print("Tracking stopped:");
         lcd.setCursor(0,2);
         lcd.print("Storing tracker...");
         delay(2000);
         break;
      }
    }
    lcd.clear();
    }
    turnDetected = false;    

//*******************  BEGIN TEMPERATURE FUNCTIONS ON LCD  *********************

 //for(int temp_interval = 0; temp_interval <=4; temp_interval++) //interval to display temp screen
// {
  
  if (currentMillis - previousMillis <= interval_1)
  {  
   
  hum_2 = dht.readHumidity();
  temp_2 = dht.readTemperature();
  delay(1000); 

  char tempF[6]; 
  char humF[6];
  dtostrf(temp_2, 5, 1, tempF);
  dtostrf(hum_2, 2, 0, humF);

  lcd.setCursor(0,0);
  lcd.print("-Temperature:"); 
  lcd.print(tempF);
  lcd.print((char)223);
  lcd.print("C ");
  lcd.setCursor(0,2);
  lcd.print("-Humidity: ");
  lcd.print(humF);
  lcd.print("%");
 
   if (temp_2 > temp_max) //max temperature
     temp_max = temp_2;   
 
   if (temp_2 < temp_min) //min temperature
     temp_min = temp_2;   

   if (hum_2 > hum_max) //max humidity  
     hum_max = hum_2;

   if (hum_2 < hum_min) //min humidity   
     hum_min = hum_2;
    
   
   lcd.setCursor(0,1);
   String temp_status_line = String("Min: ") += String(temp_min) += String(char(223)) += String("C ") += String("Max: ") += String(temp_max) += String(char(223)) += String("C ");
   lcd.print(temp_status_line);
   
   lcd.setCursor(0,3);
   String hum_status_line = String("Min: ") += String(hum_min) += String("% ") += String("Max: ") += String(hum_max) += String("%");
   lcd.print(hum_status_line);
 
   lcd.clear(); 
  }// end of temp loop screen



//*******************  BEGIN TIME FUNCTIONS ON LCD  ********************
 
 //for(int time_interval = 0; time_interval <= 100; time_interval++) //interal to display time screen
 //{ 
   
 if (currentMillis - previousMillis >= interval_1)
   //attachInterrupt (PinCLK, motorStop, FALLING); //  
  {    
    DateTime now = rtc.now(); //get date and time
    
    int print_month = now.month();
    
    switch(print_month) //output current month
    {            
      case 1:
      lcd.print("January");
      break;
      
      case 2:
      lcd.print("February");
      break;
      
      case 3:
      lcd.print("March");
      break;
      
      case 4:
      lcd.print("April");
      break;
      
      case 5:
      lcd.print("May");
      break;
      
      case 6:
      lcd.print("June");
      break;
      
      case 7:
      lcd.print("July");
      break;
      
      case 8:
      lcd.print("August");
      break;
      
      case 9:
      lcd.print("September");
      break;
      
      case 10:
      lcd.print("October");
      break;
      
      case 11:
      lcd.print("November");
      break;
      
      case 12:
      lcd.print("December");
      break;      
    }      
    
    lcd.print('/');
    lcd.print(now.day(), DEC);
    lcd.print('/'); 
    lcd.print(now.year(), DEC);
    lcd.print(' ');  
   
    //DETERMINE AM/PM
    int hour_24, hour_12;     
    hour_24 = now.hour();
    
    if (hour_24 == 0) //output changing 24AM to 12AM    
      hour_12 = 12;
    
    
    else  //outputing 1-11PM/AM       
      hour_12 = (hour_24 % 12);    
    
    lcd.setCursor(0,1);
    lcd.print(hour_12, DEC);
    lcd.print(':');
    
    if(now.minute() < 10)    
      lcd.print("0");
      
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    
    if(now.second() < 10)    
      lcd.print("0");
    
    lcd.print(now.second(), DEC);
    
    if(hour_24 < 12)
    lcd.print("AM");
    
    else
    lcd.print("PM");       
    
    //************************ TIMER OUTPUT **********************
    
    lcd.setCursor(0,2);
    lcd.print("Track time/Rotation");
    lcd.print(char(223));
    lcd.setCursor(0,3);
    lcd.print(minute());
    lcd.print(":");
    
    if(second() < 10)     
      lcd.print("0");
    
    lcd.print(second());  
  
    //************************ EARTH DEGREE ROTATION **************  
    double deg_rot_sec = 360 / 23.934 / 3600;  //0.004178
    double deg_rot_min = 360 / 23.934 / 60;    //0.250689
    
    double rot_amount = ((deg_rot_min * minute()) + (deg_rot_sec * second()));      
    
    lcd.setCursor(11,3);
    lcd.print(rot_amount, 5);  //output the amount the earth has rotated with 5 decimal places
    lcd.print(char(223));   //degree symbol 
    
    //delay(100);  
    
    lcd.clear();
   }// end of time loop screen
 
 if (currentMillis - previousMillis >= interval_2) //reset counter 
   previousMillis = currentMillis;
  
} //end of void loop
if (currentMillis - previousMillis <= interval_1)

That line is pretty much useless because it will be true too often.

I can’t make sense of the logic of what you want to achieve. Can you write it down (in English, not code) as a series of steps with one step on each line.

…R

I actually was able to fix my issue and get rid of my 'for' loops. thanks though.