Go Down

Topic: An LED bar graph tachometer (Read 5152 times) previous topic - next topic

hoff70

The IR beam is just triggering the LED pins ON/OFF. I get a blink each time a hole in the disc comes around.  It's actually not doing much but I wanted to start by having the IR beam trigger some kind of output...

I need to figure out how to have the chip calculate RPM based on the pulses over a given time and output to different blocks of pins based in that info. I think...

PeterH

Well, you need to measure or calculate the RPM, certainly. If you have an input that is pulsing once per revolution, measuring RPM is just a matter of timing or counting those pulses.

Outputting the RPM value on your LEDs is an unrelated and much easier problem.
I only provide help via the forum - please do not contact me for private consultancy.

hoff70

Yep, 1 pulse per rev. I figure I need to sample it over time and then store that value and output it some way. I'm guessing the sample time will dictate how rapidly the display updates.

hoff70

#18
Jun 10, 2012, 02:29 am Last Edit: Jun 10, 2012, 08:16 pm by hoff70 Reason: 1
Well, I finally got the HE sensors in and figured out how to wire them up. Pretty neat little devices!

Code: [Select]
//-----------------------------------------------
volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;
void setup()
{
  Serial.begin(9600);
  attachInterrupt(0, rpm_fun, RISING);
  rpmcount = 0;
  rpm = 0;
  timeold = 0;
}
void loop()
{
  if (rpmcount >= 20) {
    //Update RPM every 20 counts, increase this for better RPM resolution,
    //decrease for faster update
    rpm = 30*1000/(millis() - timeold)*rpmcount;
    timeold = millis();
    rpmcount = 0;
    Serial.println(rpm,DEC);
  }
}
void rpm_fun()
{
  rpmcount++;
  //Each rotation, this interrupt function is run twice
}
//-----------------------------------------------


I've been puttering with this code some and I imagine it holds the key to what I'm trying to accomplish.

Any hints, pointers?  I'd like to get something sort of working this weekend.

Thanks.

I also found this:

http://www.hobbytronics.co.uk/arduino-tutorial11-hall-effect

At least I have input to the Arduino with an HE sensor...

hoff70

#19
Jun 10, 2012, 11:03 pm Last Edit: Jun 11, 2012, 12:11 am by hoff70 Reason: 1
Not much action here but I've been making baby steps:

Code: [Select]
//code by Crenn from http://thebestcasescenario.com
//project by Charles Gantt from http://themakersworkbench.com


/*To disable interrupts:
cli();                // disable global interrupts

and to enable them:  
sei();                // enable interrupts
*/


                                  //Varibles used for calculations
int NbTopsFan;
int Calc;

                                 //The pin location of the sensor
int hallsensor = 2;
int ledPin = 4;           //$$STUFF I ADDED$$


                       
typedef struct{                  //Defines the structure for multiple fans and their dividers
 char fantype;
 unsigned int fandiv;
}fanspec;

//Definitions of the fans
fanspec fanspace[3]={{0,1},{1,2},{2,8}};

char fan = 1;   //This is the varible used to select the fan and it's divider, set 1 for unipole hall effect sensor
              //and 2 for bipole hall effect sensor


void rpm ()      //This is the function that the interupt calls
{
NbTopsFan++;
}

             //This is the setup function where the serial port is initialised,
            //and the interrupt is attached
void setup()
{
pinMode(hallsensor, INPUT);
Serial.begin(9600);
attachInterrupt(0, rpm, RISING);
pinMode(ledPin, OUTPUT);    ////$$STUFF I ADDED$$$
}
void loop ()
{
  NbTopsFan = 0; //Set NbTops to 0 ready for calculations
  sei(); //Enables interrupts
  delay (1000); //Wait 1 second
  cli(); //Disable interrupts
  Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv); //Times NbTopsFan (which is apprioxiamately the fequency the fan is spinning at) by 60 seconds before dividing by the fan's divider
  Serial.print (Calc, DEC); //Prints the number calculated above
  Serial.print (" rpm\r\n"); //Prints " rpm" and a new line
 
  //$$STUFF I ADDED$$/////////////////////////////////////////////////////////////////////////////
  if (Calc > 40)
  {
    digitalWrite (4, HIGH);
    delay (500);
  }
  if (Calc < 40)
  {
    digitalWrite (4, LOW);
  }
}


I didn't do much but I am getting serial output of RPM to the serial monitor and I'm getting a single LED to turn ON/OFF with RPM changes. My RPM measurement doesn't seem to be accurate but it is proportional so I figure I can tinker with the code to get it working. I guess the numbers really don't matter as long as I can get the output to register correctly. I'm not going to be using the serial data anyway.

I did get the hall effect sensor working after learning that I needed a resistor between the pos and signal  :smiley-roll-sweat:

Just one sad little LED for output but it's a start:



No little magnets to mount on my test rig so I'm stuck waving a big one over the HE sensor for now... I considered using a PC fan 3rd wire for input but I want to stick with what I'm going to use in the final build so I don't complicate things.

Would someone mind explaining what's going on in the code? Especially this line:

fanspec fanspace[3]={{0,1},{1,2},{2,8}};

Thanks.


More stuff:

Code: [Select]
//code by Crenn from http://thebestcasescenario.com
//project by Charles Gantt from http://themakersworkbench.com


/*To disable interrupts:
cli();                // disable global interrupts

and to enable them:  
sei();                // enable interrupts
*/


                                  //Varibles used for calculations
int NbTopsFan;
int Calc;

                                 //The pin location of the sensor
int hallsensor = 2;
int ledPin = 4;           //$$STUFF I ADDED$$
int ledPin1 = 5;
int ledPin2 = 6;
int ledPin3 = 7;

                       
typedef struct{                  //Defines the structure for multiple fans and their dividers
 char fantype;
 unsigned int fandiv;
}fanspec;

//Definitions of the fans
fanspec fanspace[3]={{0,1},{1,2},{2,8}};

char fan = 1;   //This is the varible used to select the fan and it's divider, set 1 for unipole hall effect sensor
              //and 2 for bipole hall effect sensor


void rpm ()      //This is the function that the interupt calls
{
NbTopsFan++;
}

             //This is the setup function where the serial port is initialised,
            //and the interrupt is attached
void setup()
{
pinMode(hallsensor, INPUT);
Serial.begin(9600);
attachInterrupt(0, rpm, RISING);
pinMode(ledPin, OUTPUT);////$$STUFF I ADDED$$$
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
}
void loop ()
{
  NbTopsFan = 0; //Set NbTops to 0 ready for calculations
  sei(); //Enables interrupts
  delay (1000); //Wait 1 second
  cli(); //Disable interrupts
  Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv); //Times NbTopsFan (which is apprioxiamately the fequency the fan is spinning at) by 60 seconds before dividing by the fan's divider
  Serial.print (Calc, DEC); //Prints the number calculated above
  Serial.print (" rpm\r\n"); //Prints " rpm" and a new line
 
  //$$STUFF I ADDED$$/////////////////////////////////////////////////////////////////////////////
  if (Calc > 40)
  {
    digitalWrite (4, HIGH);
    delay (100);
  }
  if (Calc < 40)
  {
    digitalWrite (4, LOW);
  }
  if (Calc > 100)
  {
    digitalWrite (5, HIGH);
    delay(100);
  }
  if (Calc < 100)
  {
    digitalWrite (5, LOW);
  }
  //////
   if (Calc > 240)
  {
    digitalWrite (6, HIGH);
    delay(100);
  }
  if (Calc < 240)
  {
    digitalWrite (6, LOW);
  }
  /////
   if (Calc > 300)
  {
    digitalWrite (7, HIGH);
    delay(100);
  }
  if (Calc < 300)
  {
    digitalWrite (7, LOW);
  }
 
 
 
}


It's clunky but it seems to work!

Also, If all goes well, (And it looks like it very well may  :)) I would like to do a permanent install. I don't want to use my UNO for it but rather build a bare bones chip setup. Any input on this? I suppose I would at least need a crystal as well as a power supply. Would be neat to (Try to) build!

hoff70

Just another update. I will get this finished some day...

I want this to be a "stand alone" project so I started fooling with ATtiny 85's. Thanks to the kind and patient folks here I've made some progress on that front.

I believe I may be able to run this project with an ATtiny 85. I found this code which runs well on it:

Code: [Select]
void setup() {                     //nothing to do in setup
}

byte t = 0;                         //used for looping between LED's in a knight rider kind of fashion
void loop() {
  for (t = 0; t < 10; t++) {
    charliePlex(t);               //switch on LED number T
    delay(75);                     // Wait a bit
  }
  for (t = 9; t >= 0; t--) { // Reverse the run
    charliePlex(t);                // switch on LED number T
    delay(60);                      // delay a bit
  }
  charliePlex(10);               //switch off all LEDs I only had 9, so if you try to switch on any
                                         //bigger number, they would all be off.
  delay(500);                      //big delay before we do it all over again
}

void charliePlex(byte i) {   // This function switches on one of the LED's. Due to the way I
                                        // laid out my circuit, the pins are not exactly in a logical order,
                                        // but if you understand the concept, it's easy to tune it for your circuit.
  for (int t = 0; t < 4; t++) pinMode(t, INPUT); // I used IO ports 0-4. the ATTINY85 only has 5
                                                                    //(or 6 if you sacrifice reset) GPIO's. This loop will switch
                                                                    // off all the LED's, because it sets the IO ports to input
                                                                    // (high impedance) mode.
  switch (i) {                                       //decide which LED we want to switch on
    case 0: charlieSwitch(2, 0);            //The first LED is wired from Pin 2 to Pin 0
     break;
    case 1: charlieSwitch(0, 2);            // the second LED is the reverse of the LED above
     break;
    case 2: charlieSwitch(1, 0);
     break;
    case 3: charlieSwitch(0, 1);
     break;
    case 4: charlieSwitch(1, 2);
     break;
    case 5: charlieSwitch(2, 1);
     break;
    case 6: charlieSwitch(3, 2);
     break;
    case 7: charlieSwitch(2, 3);
     break;
    case 8: charlieSwitch(3, 1);
     break;
   }
}

void charlieSwitch(byte pin1, byte pin2) {            //This function merely sets the ports as output,
                                                                      // and drives the first one HIGH and the Second one LOW
     pinMode(pin1, OUTPUT);
     pinMode(pin2, OUTPUT);
     digitalWrite(pin1, HIGH);
     digitalWrite(pin2, LOW);
}


It uses 4 pins to charlieplex 9 LED's leaving 1 pin for input. I'm hoping I can use the last pin for input from the HE sensor but I was wondering if I may need an external clock like a crystal to get it working.  It's not going to be a high precision instrument so maybe the chip alone will do it?

Any input would be most welcome!

Go Up