ATTINY45, Solution/Substitution for FreqCount Library?

I have been working on a simple project.

So far the code i have come up with that works on the Uno is

#include <FreqCount.h>
const int ledPin =  13;
const int SpinPin =  12;

void setup() {
  pinMode(ledPin, OUTPUT); // initialize the LED pin as an output:
  pinMode(SpinPin, OUTPUT); // initialize the LED pin as an output:
  Serial.begin(57600);
  FreqCount.begin(100);
}

void loop() {
  if (FreqCount.available()) {
    unsigned long count = FreqCount.read();
    Serial.println(count);
    if(count >=400 && count <= 1400)
    {
      digitalWrite(ledPin, HIGH); // Enables Stepper Current Opto USE RESISTOR!
    }
    else {
      // turn LED off:
      digitalWrite(ledPin, LOW);
    }
    if (digitalRead(13) == HIGH  && digitalRead(3) == HIGH) 
    { 
      digitalWrite(SpinPin, HIGH); // Enables Spindle Opto USE RESISTOR!
    } 
    else {
      // turn LED off:
      digitalWrite(SpinPin, LOW); 
    }
  }
}

I would like to get this functionality working on an ATTINY45. My problem is the FreqCount library i am using on the Uno doesn’t seem to want to run on the ATTINY45.

Are there some things i can edit within the library to get this up and working? Or would i be better off switching to a different bit of code altogether to count the incoming pulses?

Thanks!

I strongly suspect it isnt working on the ATTiny45 as it doesn't have the hardware timer that the library uses.

You may be able to modify the library to use a different timer, assuming there is one free on the ATTiny45

Or possibly use the ATTiny85, as it may have more timers - but your'd need to check the spec

Of if size isnt a major issue, just buy a Arduino Nano or Pro Mini or Micro board instead.

Thats the problem, packaging size is important.

The input is a 12.5khz square wave, i just need to turn the outputs on when its present and off when it is not.

Th pulse in arduino function is supposed to work on the attiny45, so i figure i can rewrite my little code to use hardware that the attiny45 does have…. Still along ways to go on understanding timers and counters.

I think trying to decode the library is WAY over my head at this point. Unless someone else has done it, and can point me to exactly what to change.

The whole point of what I'm doing is to end up on an attiny45 {or 85}. I don't mind writing code specifically for it. But I'm so new to all this, its proving a much larger challenge than i ever expected!

The IDE throws an error code when i try to compile saying unknown chip type, edit timer and counter definitions in the library.

Any idea what these definitions are specifically, where to find them either in spec or in the library?

At that frequence you could use pulseIn() function on your Attiny45.
Preferrable running it @ 8MHz

I just tried it and the results were 40-41

This is exactly what i am working on now.

Progress is slow, i will post what i have so far. I haven't had a chance to test it yet.

I believe I'm trying to get the pulsein to print to serial, so i can see what kind of value it returns.

Then i can use that value to plug into my code….?

Just so we are on the same page, I've had an arduino for about a week. Worked my way through the basic inventors kit, and here we stand. I have zero programming experience, so I'm more or less trying this in pure brute force fashion.

Cutting and pasting bits of code from all over, then hoping it compiles. Then again hoping it works.

I build little machines to do various things around my workshop. this feature is about the only high tech piece on any of them, but you know. It keeps my fingers attached, so its important to me.

Thanks again for all your help. Every little nudge in the right direction helps more than you could imagine.

int pin = 7;
unsigned long duration;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the pushbutton's pin an input:
  pinMode(pin, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  duration = pulseIn(pin, HIGH);
  // read the input pin:
  int pulse = digitalRead(pin);
  // print out the state of the button:
  Serial.println(pulse);
  delay(1);        // delay in between reads for stability
}

The input is a 12.5khz square wave, i just need to turn the outputs on when its present and off when it is not.

If all you need to do is detect if the square wave is present or not but don’t need to check it’s frequency and duty cycle are correct then how about using an RC circuit connected to an analogue input pin to detect it. Easy to do on an tiny85. You could also use the RC circuit output into a comparator and dispense with the tiny85.

EDIT: If you need to check duty cycle and frequency then use interrupt pin on a tiny85.

Well, there are other inputs besides the square wave.

When the wave is present the device is "Ready" or "Armed" at this time one output changes states the other waits for a second input before it "turns on"

When the wave is not present, or is "slow" the device goes "Not Ready" or "Safe" no matter what the inputs are saying, everything turns off without the square wave.

The 3rd party software being used to control the machine is glitchy. Sometimes when it starts it runs slow. In these situations i would like the square wave that is being output to NOT arm the machine. A simple reboot of the software solves the issue every time.

Having the chip doing some sort of basic counting, in my mind anyways, allows me to set a threshold "frequency" to turn on and off at. regardless of what the reference number actually correlates too.

I've read pulse in on the attiny45 to be good to 100khz. {I've got a couple attiny45 laying here}

Am i even on the right track? lol.

Still baffled!!

Any closer to being what i need? I think he said just change interrupt pins and frequency scalar for my application.

I’m trying! Just clueless! lol

//http://www.instructables.com/id/Arduino-Timer-Interrupts/

void setup(){

cli();//stop interrupts

//set timer0 interrupt at 2kHz
  TCCR0A = 0;// set entire TCCR0A register to 0
  TCCR0B = 0;// same for TCCR0B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 2khz increments
  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS01 and CS00 bits for 64 prescaler
  TCCR0B |= (1 << CS01) | (1 << CS00);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);

//set timer1 interrupt at 1Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);  
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

//set timer2 interrupt at 8kHz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 8khz increments
  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS21 bit for 8 prescaler
  TCCR2B |= (1 << CS21);   
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);


sei();//allow interrupts

}//end setup

Now I think you are over complicating things.

Like I said, the pulseIn function will work on a Attiny45.

Going back to your sketch in reply #4, you already has most of the solution.

You measure the pulse

 int pulse = digitalRead(pin);

Now you know that if there is a frequnce of 12500 Hz the pulsein will return a value of 40-41
The only thing you are missing is a if statement

if (pulse>38){
// we have a pulse do something
}else{
//we have no pulse do something other
}

ahhh ok.

I like simple! Ive been chasing my tail it seems. Just trying to find a working example of something close to work backwards from.

I wasn’t sure what you meant by the results were 40-41. I meant to ask for clarification on that.

below is the original if/else statements i was using, I’ve made some changes that i believe are in tune with the pulsein function.

i still need to change the pin assignments to coincide with the attiny45, which leads me to my next question.

For pulse in, does it matter which at tiny pin i am using for the square wave input?

Thank you greatly!

 if(pulse >=37 && pulse <= 50){
      digitalWrite(ledPin, HIGH); // Enables Stepper Current Opto USE RESISTOR!
    }else {
      // turn LED off:
      digitalWrite(ledPin, LOW);
    }
    if (digitalRead(13) == HIGH  && digitalRead(3) == HIGH) 
    { 
      digitalWrite(SpinPin, HIGH); // Enables Spindle Opto USE RESISTOR!
    } else {
      // turn LED off:
      digitalWrite(SpinPin, LOW); 
    }

I wasn’t sure what you meant by the results were 40-41

At a frequence of 12500 each pulse is 1/12500 = 80 microsecond long.
With the pulseIn you only measure how long it is high or low, so at 50% duty cycle the result wil be 80/2=40 microseconds.

For pulse in, does it matter which at tiny pin i am using for the square wave input?

No you can use any pin (except, Vcc, grnd od reset ofcource)

Erni:

I wasn't sure what you meant by the results were 40-41

At a frequence of 12500 each pulse is 1/12500 = 80 microsecond long.
With the pulseIn you only measure how long it is high or low, so at 50% duty cycle the result wil be 80/2=40 microseconds.

For pulse in, does it matter which at tiny pin i am using for the square wave input?

No you can use any pin (except, Vcc, grnd od reset ofcource)

Awesome thanks for the explanation! On my drive home i was wondering how 40 pertained to the 12500 frequency. Makes total sense now! I was expecting to see something in the 80micros/.08millis range. It never occurred to me half that time is spent low.

Getting ready to get this all plugged up and give it a whirl.

Lets hope for a favorable result!

Alright I'm stuck…

What am i missing here?

Using the code i posted in #4 {and every variation i can think of} i am not able to get the return of approx 40micros.

With the 12500 signal absent i am getting a slow vertical string of 1's about every second.
With the signal present, i am getting a very rapid string of 0's

I have fiddled with the code a bunch, but am not able to get results in the serial monitor that i am expecting.

Seems like their is some sort of math or scalar that I'm missing somewhere?

Again the code is

int pin = 7;
unsigned long duration;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the pushbutton's pin an input:
  pinMode(pin, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  duration = pulseIn(pin, HIGH);
  // read the input pin:
  int pulse = digitalRead(pin);
  // print out the state of the button:
  Serial.println(pulse);
  delay(1);        // delay in between reads for stability
}
// the loop routine runs over and over again forever:
void loop() {
  duration = pulseIn(pin, HIGH);
  // read the input pin:
 // int pulse = digitalRead(pin);  //<<<<<<<<<<<<<<
  // print out the state of the button:
  //Serial.println(pulse);  //<<<<<<<<<<<<<<<<<<<
  Serial.println(duration);  //<<<<<<<<<<<<<<<<<<<
  delay(1);        // delay in between reads for stability
}

Your reading the pin using pulseIn and doing nothing with the result but then read the pin using digitalRead and print that result.

That much i understand.

I was at one point getting it to print the input pin number at one time, which made me realize i have some sort of syntax error? Or just bad code in general.

So how do i get the return of pulsein to print to the serial window?

I know it seems simple to you guys, but my mind is reeling over here.

int pin = 7;
unsigned long duration;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the pushbutton's pin an input:
  pinMode(pin, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  duration = pulseIn(pin, HIGH);
  // read the input pin:
 
  // print out the state of the button:
 Serial.println(duration);
  delay(1);        // delay in between reads for stability
}

When i use that code, i get a slow string of 0’s with no signal present, and string of wild numbers when the signal is present.

It seems like pulsein is working, I’m just getting a garbage return. I know its a simple error, but man. I’m having a tough time finding it. heres a screen cap of serial monitor window using the above code.

0’s are signal off, crazy numbers are with the square wave running.

I fell asleep on the couch working on this, woke up in the middle of the night worked on it some more. lol. Im going back to bed! Hopefully it will start to make sense in the morning :wink:

The code you have should be doing what you want. The only reason I can think the values vary so much is the pin is floating, the signal is not a clean TTL level or not a constant 50% duty cycle. You could try either a pullup or pulldown resistor on the input pin to see if the results stabilize. Pullup could be done on the chip by using pinMode(pin, INPUT_PULLUP); instead of pinMode(pin, INPUT); but you will maybe need to use LOW in the pulseIn instead of HIGH. For pulldown use the same code you currently have (INPUT) and put a 10K resistor between the input pin and ground.

Ok so right now i am using the code i posted last night {this morning?}

With the charge pump signal running, i am getting a return of 33-40 in the serial monitor window.

I am using a pull down resistor, 10k right now. The signal seems clean enough with or without it however, i think my issue last night was lack of sleep induced, incorrect connection on the breadboard.

This made me wonder what Erni was using to create his 12500hz signal when he got the return of 40-41. I assume some sort of bench test unit. The charge pump signal generated by mach3 is famously flakey and most calibrate the circuit to react to anything above 10000hz and below 15000hz. I believe my return puts me well within that range.

So if I’m correct, i just need to add my if/else statements and i should be off to the races!

Does the attiny have internal pullups? Or should i stick with my code now and external pulldown? hmm.

Thanks you two! Im not out the woods yet, but i can see light! I earnestly appreciate folks like you taking your own time to help folks like me.

int pin = 7;
unsigned long duration;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the pushbutton's pin an input:
  pinMode(pin, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
  delay(1);        // delay in between reads for stability
}

This made me wonder what Erni was using to create his 12500hz signal when he got the return of 40-41

I was using my Arduino UNO and the tone library.

tone(7,12500)

An I measured the 40-41 microseconds on an ATtiny85 using a sketch much like the one you are using now.
BTW the values you get now seems OK, as youn only have to decide if there is a signal or not.

Ok, Heres my progress thus far.

I got it working, however i have to lower my threshold to about 20 to get a solid output. When i set the" if(duration >=20 " threshold closer to the return value the output led blinks or flickers.

secondly. The circuit turns on instantly with the presence of 12500hz signal, however once the signal dissolves it takes one second for the circuit to turn off.

I assume pulsein is polling in 1000ms intervals? Is there a simple way to correct this?

Given the bugs above, which are annoying but workable i went ahead and ported my code onto the ATTINY45. It is working on the attiny45 the same as it was on the arduino.

So now i must address these two issues, but it otherwise seems to be working. Which is hopeful!

The code also seems to be scraggly, and have a lot of curly brackets. Could excessive curly brackets be causing the flicker or delay? Maybe a quicker polling interval will reduce the flicker as well?

int inPin = 3;
const int ledPin =  2;
const int SpinPin =  1;
unsigned long duration;


void setup() {
  pinMode(ledPin, OUTPUT); // initialize the LED pin as an output:
  pinMode(SpinPin, OUTPUT); // initialize the LED pin as an output:
  pinMode(inPin, INPUT); // make the pin an input:
  
}

void loop() {
  duration = pulseIn(inPin, HIGH);
     if(duration >=20 && duration <= 50)
  {
    digitalWrite(ledPin, HIGH); // Enables Stepper Current Opto USE RESISTOR!
  }
  else{
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
  if (digitalRead(2) == HIGH  && digitalRead(4) == HIGH) 
  { 
    digitalWrite(SpinPin, HIGH); // Enables Spindle Opto USE RESISTOR!
  }
  else{
    // turn LED off:
    digitalWrite(SpinPin, LOW); 
  }
 
}

once the signal dissolves it takes one second for the circuit to turn off.

The timeout for the pulseIn() function is 1 second, so you could set it to a lower value

pulseIn(pin, value, timeout)

http://arduino.cc/en/Reference/pulseIn