Pages: [1]   Go Down
Author Topic: tachometer programming help needed  (Read 775 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
Full Member
***
Karma: 0
Posts: 116
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hi

just been working for a bit with trying to get a optical tachometer to control a range of parameters, so the faster an object spins the higher the pitch, the brighter the lights etc. I am almost there - but I just can't get past a syntax error - whenever I compile the code below I get the error message:

error: expected unqualified-id before 'else

i know it must be something really easy but I have been staring at the screen for a while with no luck - does anyone have any suggestions?

Code:
/*
 * Optical Tachometer
 *
 * Uses an IR LED and IR phototransistor to implement an optical tachometer.
 * The IR LED is connected to pin 13 and ran continually. A status LED is connected
 * to pin 12. Pin 2 (interrupt 0) is connected across the IR detector.
 *
 *
 */
//#define DEBUG      
 
int ledPin = 13;                // IR LED connected to digital pin 13
int statusPin = 12;
int lightPin = 11;// LED connected to digital pin 12
int brightness = 0;
int delay_time = 40; // delay for this amount each write cycle.
int noteDown = LOW;
byte MIDI_channel = 0;
byte cc_number = 0;
byte incomingByte;
byte button;
byte note;
byte printing_byte = 0;
int Value = 0;
int midi_pitch = 0;
int mappedrpm = 0;
int state=0;
#ifdef DEBUG
const int DEBUG_RATE = 9600;        // Serial debugging communicates at 9600 baud
const int SERIAL_PORT_RATE = DEBUG_RATE;
#else
const int MIDI_BAUD_RATE = 31250;   // MIDI communicates at 31250 baud
const int SERIAL_PORT_RATE = MIDI_BAUD_RATE;
#endif



volatile byte rpmcount;
volatile int status;

unsigned int rpm;

unsigned long timeold;

 void rpm_fun()
 {
   //Each rotation, this interrupt function is run twice, so take that into consideration for
   //calculating RPM
   //Update count
      rpmcount++;
      
   //Toggle status LED  
   if (status == LOW) {
     status = HIGH;
   } else {
     status = LOW;
   }
   digitalWrite(statusPin, status);
 }

void setup()
 {
     state = 0;
    
   Serial.begin(SERIAL_PORT_RATE);
   //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
   //Triggers on FALLING (change from HIGH to LOW)
   attachInterrupt(0, rpm_fun, FALLING);
  
   //Turn on IR LED
   pinMode(ledPin, OUTPUT);
   digitalWrite(ledPin, HIGH);
  
   //Use statusPin to flash along with interrupts
   pinMode(statusPin, OUTPUT);

   rpmcount = 0;
   rpm = 0;
   timeold = 0;
   status = LOW;
 

 }

 void loop()
 {
   //Update RPM every second
   delay(800);
   //Don't process interrupts during calculations
   detachInterrupt(0);
   //Note that this would be 60*1000/(millis() - timeold)*rpmcount if the interrupt
   //happened once per revolution instead of twice. Other multiples could be used
   //for multi-bladed propellers or fans
   rpm = 3*1000/(millis() - timeold)*rpmcount;
   timeold = millis();
   rpmcount = 0;
  
  brightness = map(rpm, 0, 50, 0, 255);
  analogWrite(lightPin, brightness);
 
   if(rpm > 127) {
    printing_byte = 127;
  
   }

 }
void checkButton(){    
  printing_byte = map(rpm, 0, 50, 0, 127);{
  if(printing_byte >= 120) noteSend(0x90, 65, 0); else noteSend(0x90, 65, 127);
  }
}


else
{

 #ifdef DEBUG
  Serial.println(rpm, DEC);
 #else
  noteSend(MIDI_channel, cc_number, printing_byte);
 #endif
   //Write it out to serial port
   //Restart the interrupt processing
 attachInterrupt(0, rpm_fun, FALLING);
}

void noteSend(byte MIDI_channel, byte cc_number, byte printing_byte)
{
 Serial.print(B10110000 + MIDI_channel,BYTE);
 Serial.print(cc_number,BYTE);
 Serial.print(printing_byte,BYTE);
}
 
    
Logged

Omaha
Offline Offline
Full Member
***
Karma: 0
Posts: 187
AC0KG
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Reformat your code with a standard indention style and you will discover the source of your problem.

Edit: I should point you to the Auto Format menu option in the Tools menu smiley
« Last Edit: August 11, 2009, 07:48:45 pm by DaveK » Logged


Omaha
Offline Offline
Full Member
***
Karma: 0
Posts: 187
AC0KG
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Incidentally, blocking problems of this sort are extremely common for new programmers. I've put an issue into the Arduino issues list on GoogleCode requesting some attention to this problem.

The Tools|AutoFormat feature helps with this once the user realizes what has happened, but I'd like to see graphical outlining so that the user can see it when it happens.
« Last Edit: August 11, 2009, 07:47:50 pm by DaveK » Logged


London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Note that the IDE has an 'Auto Format' option in the tools menu that makes it easier to see the code structure. It's not as elaborate as Dave is suggesting but it will help.

Looking at the code I wonder if this is too complex an app to start with. My advice is to start with something simple so you can get to grips with how to use code block to write conditional statements and when you are comfortable with that move on to things like this that attach interrupts.

It may delay getting this particular project started but you will have a much easier job getting code to work if you spend a little time learning the fundamentals.

Have fun!
Logged

UK
Offline Offline
Full Member
***
Karma: 0
Posts: 116
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

thank you for all the replies - afraid the 'Auto format' did not help. I was not aware of that function but in this instance I could not see what changes it may have made to the structure (layout) of the code. will persevere. I am aware that this is out of my comfort zone so to speak, but I believe that by setting yourself hard challenges in fields you are not fully familiar with is a good way of learning.
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is a fragment from your post:
Code:
void checkButton(){    
  printing_byte = map(rpm, 0, 50, 0, 127);{
  if(printing_byte >= 120) noteSend(0x90, 65, 0); else noteSend(0x90, 65, 127);
  }
}

else
{
 

After using auto format:

Code:
void checkButton(){    
  printing_byte = map(rpm, 0, 50, 0, 127);
  {
    if(printing_byte >= 120) noteSend(0x90, 65, 0);
    else noteSend(0x90, 65, 127);
  }
}


else
{
Note how the curly brace before the if statment becomes more obvious.  This brace serves no purpose and can be a clue that your problem is it that you have braces in the wrong place. Auto Format will not fix coding errors but by using a standard coding style it is easier to see when you have misplaced a brace.
« Last Edit: August 12, 2009, 06:01:49 am by mem » Logged

UK
Offline Offline
Full Member
***
Karma: 0
Posts: 116
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for the help - sometimes I just miss the little details and remain totally blind to them.
I actually ended up going about writing the code in a different way, just because the way that I was sending the midi data did not work (i.e. when I wanted to send both midi CC and NoteON / OFF ). The new code (as can be seen below) works great, but i have reached a new stumbling block  - as is usually the case.
I need the code to send a single NotON event when the rpm count goes over 120, this triggers a midi sequence of av events (Ableton and Modul8), however as the rpm count is constatly feeding out data the code continually sends the NoteON message for as long as the rpm count is above 120. Is there a way to make it so that it sends just one noteON event when the rpm count goes over 120 first time?

any help is greatly appreciated

Code:
/*
 * Optical Tachometer
 *
 * Uses an IR LED and IR phototransistor to implement an optical tachometer.
 * The IR LED is connected to pin 13 and ran continually. A status LED is connected
 * to pin 12. Pin 2 (interrupt 0) is connected across the IR detector.
 *
 *
 */
//#define DEBUG      

int ledPin = 13;                // IR LED connected to digital pin 13
int statusPin = 12;
int lightPin = 11;// LED connected to digital pin 12
int brightness = 0;
int delay_time = 40; // delay for this amount each write cycle.
int noteDown = LOW;
byte MIDI_channel = 0;
byte cc_number = 0;
byte incomingByte;
byte button;
byte note;
byte printing_byte = 0;
int Value = 0;
int midi_pitch = 0;
int mappedrpm = 0;
int state=0;
#ifdef DEBUG
const int DEBUG_RATE = 9600;        // Serial debugging communicates at 9600 baud
const int SERIAL_PORT_RATE = DEBUG_RATE;
#else
const int MIDI_BAUD_RATE = 31250;   // MIDI communicates at 31250 baud
const int SERIAL_PORT_RATE = MIDI_BAUD_RATE;
#endif



volatile byte rpmcount;
volatile int status;

unsigned int rpm;

unsigned long timeold;

void rpm_fun()
{
  //Each rotation, this interrupt function is run twice, so take that into consideration for
  //calculating RPM
  //Update count
  rpmcount++;

  //Toggle status LED  
  if (status == LOW) {
    status = HIGH;
  }
  else {
    status = LOW;
  }
  digitalWrite(statusPin, status);
}

void setup()
{
  state = 0;

  Serial.begin(SERIAL_PORT_RATE);
  //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
  //Triggers on FALLING (change from HIGH to LOW)
  attachInterrupt(0, rpm_fun, FALLING);

  //Turn on IR LED
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);

  //Use statusPin to flash along with interrupts
  pinMode(statusPin, OUTPUT);

  rpmcount = 0;
  rpm = 0;
  timeold = 0;
  status = LOW;


}

void loop()
{
  //Update RPM every second
  delay(800);
  //Don't process interrupts during calculations
  detachInterrupt(0);
  //Note that this would be 60*1000/(millis() - timeold)*rpmcount if the interrupt
  //happened once per revolution instead of twice. Other multiples could be used
  //for multi-bladed propellers or fans
  rpm = 3*1000/(millis() - timeold)*rpmcount;
  timeold = millis();
  rpmcount = 0;
  attachInterrupt(0, rpm_fun, FALLING);
  brightness = map(rpm, 0, 50, 0, 255);
  analogWrite(lightPin, brightness);
  printing_byte = map(rpm, 0, 50, 0, 127);{
  midiOUT(0xB0, 7, printing_byte);
  }

    if(printing_byte >= 120){
    midiOUT(0x90, 65, 127);
    }
  
}




  //Write it out to serial port
  //Restart the interrupt processing
  


void midiOUT(char command, char value1, char value2) {
  Serial.print(command, BYTE);
  Serial.print(value1, BYTE);
  Serial.print(value2, BYTE);

}

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 73
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

im no expert to all this but isnt

Code:
if(rpm > 127) {
    printing_byte = 127;
  
   }
                    //if you want it to call a function shouldnt it be INSIDE   the }} etc etc



 }
void checkButton(){    
  printing_byte = map(rpm, 0, 50, 0, 127);{
  if(printing_byte >= 120) noteSend(0x90, 65, 0); else noteSend(0x90, 65, 127);
  }
}


else
{

 #ifdef DEBUG
  Serial.println(rpm, DEC);
 #else
  noteSend(MIDI_channel, cc_number, printing_byte);
 #endif
   //Write it out to serial port
   //Restart the interrupt processing
 attachInterrupt(0, rpm_fun, FALLING);
}



wrong?   sorry if it is correct just didnt look correct
Logged

UK
Offline Offline
Full Member
***
Karma: 0
Posts: 116
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Dustin

you are correct - but the code you are referring to is from a previous version and it did not work. The code I have posted up subsequently (the one I put up today) does. The problem with it is that it continually sends a noteON message whilst the rpm count is above 120 as opposed to just sending a single noteON the first time it detects rpm>=120
Logged

Pages: [1]   Go Up
Jump to: