Pages: [1] 2   Go Down
Author Topic: Code slows down with simple led on/off added  (Read 411 times)
0 Members and 1 Guest are viewing this topic.
The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 330
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a working piece of code that measures force with an AD converter and movement with an encoder strip. Data is transported to a PC by USB to an VB6 application. I need to add a motor control from VB6 (simple motor on motor off) to the arduino UNO. So I started with the basics of that but got stuck.

I have piece of code that switch on and off a led with processing through serial (before I implement it in VB6) . This also works fine and when I change the state in processing the led goes off imediatly and vise versa. So I took this code and pasted it in the force/motion code. The behaviour I get is that the led switch on and off in a random eratic delay. I know this is a basic problem but I am overlooking something very simple I think.

Any guidance would be appriciated.

Code for LED on off
Code:
const int ledPin = 8; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup() {
   // initialize serial communication:
   Serial.begin(9600);
   // initialize the LED pin as an output:
   pinMode(ledPin, OUTPUT);
}

void loop() {
   // see if there's incoming serial data:
   if (Serial.available() > 0) {
     // read the oldest byte in the serial buffer:
     incomingByte = Serial.read();
     // if it's a capital H (ASCII 72), turn on the LED:
     if (incomingByte == 'H') {
       digitalWrite(ledPin, HIGH);
     }
     // if it's an L (ASCII 76) turn off the LED:
     if (incomingByte == 'L') {
       digitalWrite(ledPin, LOW);
     }
   }
}


Code for force and movement with led on off added.
Code:
// Interrupt information optical encoder
// 0 on pin 2
// 1 on pin 3

//default connection arduino NANO/UNO TM7709 24 bit ADC
//DRDY = pin 11 >MOSI
//ADIO = pin 12 >MISO
//SCLK = pin 13 >SCK

//default connection arduino MEGA TM7709 24 bit ADC
//DRDY = pin 21 >MOSI
//ADIO = pin 22 >MISO
//SCLK = pin 28 >SCK

#define TM7710_DRDY        3          
#define TM7710_ADIO        4          
#define TM7710_ADIO_OUT()  DDRB|=1<<4    
#define TM7710_ADIO_IN()   DDRB&=~(1<<4)  
#define Set_TM7710_SCLK()  PORTB|=1<<5
#define Set_TM7710_ADIO()  PORTB|=1<<4
#define Clr_TM7710_SCLK()  PORTB&=~(1<<5)
#define Clr_TM7710_ADIO()  PORTB&=~(1<<4)

unsigned char x[3];
long Result;
float vref=4.57;
int motorValue ;
const int ledPin6 = 6; // the pin that the LED is attached to
 const int ledPin7 = 7; // the pin that the LED is attached to
int led = 8;
int incomingByte;      // a variable to read incoming serial data into

enum PinAssignments
{
  encoderPinA = 2,   // rigth
  encoderPinB = 3,   // left
};

volatile unsigned int encoderPos = 5000;  // a starting counterposition for the encoder
unsigned int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management

// interrupt service routine vars
boolean A_set = false;              
boolean B_set = false;

void setup()
{
  DDRB|=1<<5 ;
  Serial.begin(9600);// set baudrate for PC too!
  TM7710_Init();

  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  
 // turn on pullup resistors
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);
  

// encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE);
  
   pinMode(ledPin6, OUTPUT);
   pinMode(ledPin7, OUTPUT);
   pinMode(led,OUTPUT);

}

void loop()
{  
  /------------------------------------------ problem part ----------------------------------------
   if (Serial.available() > 0)
   {
     incomingByte = Serial.read();
     if (incomingByte == '1')
     {
       digitalWrite(ledPin6, HIGH);
       digitalWrite(ledPin7, LOW);
     }
     if (incomingByte == '0')
     {
       digitalWrite(ledPin6, LOW);
       digitalWrite(ledPin7, HIGH);
     }
   }
   /------------------------------------------------------------------------------------  
  double volt = Result * vref /16 / 6.912;

  while((PINB&(1<<TM7710_DRDY))==(1<<TM7710_DRDY));
  TM7710_start();
  TM7710_write(0x7F);        
  TM7710_ADIO_IN();          
  for(unsigned char j=0;j<3;j++)
  
  {
    x[j]=TM7710_read();
  }
  
  TM7710_ADIO_OUT();        
  TM7710_stop();
  Result=x[0];
  Result = Result * 256;
  Result = Result + x[1];
  Result = Result * 256;
  Result = Result + x[2];
  Result = Result - 6912000;

  Serial.print ("A,");
  Serial.println (volt,0);
  Serial.print("B,");
  Serial.println(encoderPos, DEC);
  Serial.print("C,");
  Serial.println (motorValue);
  
  
    rotating = true;  // reset the debouncer

  if (lastReportedPos != encoderPos) {
    
    lastReportedPos = encoderPos;
  }
}

void TM7710_start(void)  
{
  Clr_TM7710_ADIO();
  delayMicroseconds(1);
  Clr_TM7710_SCLK();
  delayMicroseconds(1);
}

void TM7710_stop(void)    
{
  Clr_TM7710_ADIO();
  delayMicroseconds(1);
  Set_TM7710_SCLK();
  delayMicroseconds(1);
  Set_TM7710_ADIO();
  delayMicroseconds(1);
}

void TM7710_write(unsigned char dd)
{
  unsigned char i;

  for(i=8;i>0;i--)
  {
    if(dd&0x80)
      Set_TM7710_ADIO();  
    else
      Clr_TM7710_ADIO();  

    delayMicroseconds(1);
    Set_TM7710_SCLK();      
    delayMicroseconds(1);
    Clr_TM7710_SCLK();      
    dd<<=1;                  
  }
}

unsigned char TM7710_read(void)
{
  unsigned char data=0,i;

  for(i=0;i<8;i++)
  {
    Set_TM7710_SCLK();                  

    data=data<<1;                                  
    if((PINB&(1<<TM7710_ADIO))==(1<<TM7710_ADIO))  
    {
      data=data+1;
    }
    delayMicroseconds(1);
    Clr_TM7710_SCLK();
    delayMicroseconds(1);
  }
  return data;
}

void TM7710_Init()
{
  TM7710_ADIO_OUT();
  delay(100);
  TM7710_stop();
  TM7710_start();
  TM7710_write(0xBF);        
  TM7710_write(0x20); //ADC preamp Gain=128
  TM7710_stop();      
}

// Interrupt on A changing state
void doEncoderA(){
  // debounce
  if ( rotating ) delay (1);  // wait a little until the bouncing is done

  // Test transition, did things really change?
  if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
    A_set = !A_set;

    // adjust counter + if A leads B
    if ( A_set && !B_set )
      encoderPos += 1;

    rotating = false;  // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state, same as A above
void doEncoderB(){
  if ( rotating ) delay (1);
  if( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    //  adjust counter - 1 if B leads A
    if( B_set && !A_set )
      encoderPos -= 1;

    rotating = false;
  }
}
« Last Edit: November 03, 2013, 01:51:16 am by backbone » Logged

Never to old to learn and I learn every day

Saskatchewan, Canada
Offline Offline
Edison Member
*
Karma: 49
Posts: 1384
Coding Geezer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, for starters, you are declaring Result, which will be initialized to 0, then the first thing you do with it is:
Code:
 double volt = Result * vref /16 / 6.912;

So, what is the value of volt, after assigning it 0 * 4.57 / 16 / 6.912 ?


Logged

Eureka, CA
Offline Offline
Full Member
***
Karma: 1
Posts: 147
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
static boolean rotating=false;      // debounce management

global variables dont need to be static.
Logged

Texas
Offline Offline
Edison Member
*
Karma: 25
Posts: 1298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
while((PINB&(1<<TM7710_DRDY))==(1<<TM7710_DRDY));
Is this basicly a delay(x) ? How long do you expect it to delay ?
Logged

Good luck, Jack

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2194
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
// interrupt service routine vars
boolean A_set = false;             
boolean B_set = false;

While you don't needed in the case of these booleans ALL var's which can be modified by the ISR should be declared as volatile.

Mark
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2194
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
 
 // turn on pullup resistors
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);

Out of date and old fashioned -lookup the current pinMode() in the reference section.

Mark
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2194
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void doEncoderA(){
  // debounce
  if ( rotating ) delay (1);  // wait a little until the bouncing is done

  // Test transition, did things really change?
  if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
    A_set = !A_set;

    // adjust counter + if A leads B
    if ( A_set && !B_set )
      encoderPos += 1;

    rotating = false;  // no more debouncing until loop() hits again
  }
}

You can't use delay inside an ISR! nor should you use Serial.print etc.

Mark
Logged

Texas
Offline Offline
Edison Member
*
Karma: 25
Posts: 1298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Mark,
What is "ISR" ?
And Why can you not use a delay() inside one?

Thanks, Jack
Logged

Good luck, Jack

Saskatchewan, Canada
Offline Offline
Edison Member
*
Karma: 49
Posts: 1384
Coding Geezer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is "ISR" ?
And Why can you not use a delay() inside one?
Interrupt Service Routine

From the attachInterrupt() function...

Quote
Inside the attached function, delay() won't work and the value returned by millis() will not increment. Serial data received while in the function may be lost. You should declare as volatile any variables that you modify within the attached function.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 222
Posts: 12519
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The behaviour I get is that the led switch on and off in a random eratic delay.

I think you're saying that the LED is switching to the correct state but there is an unexpected erratic delay between sending the command, and the LED changing state.

The code handling the serial input looks fine so it makes sense that it is switching the LED correctly. I suspect that the problem is that the other code you are executing in loop() is taking a long time to complete so the serial port handling code is only running occasionally.

You could either read through the rest of the code carefully and look for places which could take a long time to execute, or add timing code to measure how long each part of the code takes to complete which would lead you to the hotspots.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 330
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for all responses and thinking with me,
Got me offset more then I expected. :-)

@Pete": Yes you correct about the behaviour. The LED switches but not directly.

For the others the code for the ADC TM7709 came with it and if it contains wrong declaration I was not aware of. I am not that far in programming to detect such things when looking at the code. For my first purpose of using the ADC the code gave me the results I need. If it is not optimized for speed in combination with other snippets of code I was not aware of until.......  The code for the linear encoder and the interrupts I took it somewhere else and pasted it in the ADC code.

I will look with all things said at the code and implement the suggestions.
Hope that cures the problem and brings me to a higher programming level.

Paco

Let you know the progress.

 
Logged

Never to old to learn and I learn every day

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 330
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, some steps further.
I add the changes some mentioned.
Used other code without delay for the encoder.
I commented out all delays in the code for the ADC.
Same problem.
Then to troubleshoot I took out all code for the ADC!
That cured the LED problem.
So problem is inside the ADC code.

I have no idea where to look more in this ADC code then switching off the delays in microseconds.
I tested the ADC code without the micorseconds delay and the code works as the results I expect for measuring the force.

Quote
Well, for starters, you are declaring Result, which will be initialized to 0, then the first thing you do with it is:

Code:

 double volt = Result * vref /16 / 6.912;

So, what is the value of volt, after assigning it 0 * 4.57 / 16 / 6.912 ?

 @Lar3ry
That would give 0 at that moment, dont shoot me but I am missing your point.

Thanks, Paco

Logged

Never to old to learn and I learn every day

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 285
Posts: 25630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
While you don't needed in the case of these booleans ALL var's which can be modified by the ISR should be declared as volatile.
So, what you're saying (correctly, but in a very round-about way) is that not every variable that can be modified in an ISR should be qualified "volatile"?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Texas
Offline Offline
Edison Member
*
Karma: 25
Posts: 1298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Never did yet get an answer about this:
Quote
Code:
while((PINB&(1<<TM7710_DRDY))==(1<<TM7710_DRDY));
Is this basicly a delay(x) ? How long do you expect it to delay ?
It may or may not be a problem, but what do you think?
Logged

Good luck, Jack

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 330
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Jack, if I look at it with my knowledge nothing happens as long as the value stays the same, if this cause a delay I do not know. You might be correct this causes the delay. I did not made the code for the ADC and most of it for me it is "adacadabra". I will check this evening what happens if I constant change the value of the force if the led will switch quicker. Let you know.

Thanks, Paco
Logged

Never to old to learn and I learn every day

Pages: [1] 2   Go Up
Jump to: