Author Topic: Arduino Analog Instruments  (Read 2205 times)

0 Members and 1 Guest are viewing this topic.

Offline Login to see usernames

  • Global Moderator
  • Hero member
  • ****
  • Posts: 3607
Re: Arduino freq generator
« Reply #16 on: August 20, 2018, 22:23:01 pm »
i was trying to make a frequency generator with arduino and a rotary encoder... was harder than i imagined...

but i´m using the encoder to count up or down the delay time the encoder got unresponsive at low frequencies so i had to take other way

i used a interrupt based library for the encoder so it connects to A2 and A3 analog inputs..

if it is going up it sums with the delay time according to a range determined by the encoder switch connected to D4 so if i press it it can sum or subtract 1 , 10 or 100 or  for each encoder count.. the value of the delay range within is btw 1us and 16300 (thats the upper limit lowest freq)

because of the limited range the lowest freq that can be generated with delayMicrosecond function is 30Hz but using normal delay it can be much lower perhaps 0,03hz

the highest is 254khz

freq adjust

at 100hz  the smallest increase step is 0,02hz    //  dutycycle49,9%
at 1khz   the smallest increase step is 2<>2hz   //  dutycycle  49,8%
at 10khz the smallest increase step is 185<>200hz   //  dutycycle   48,6%
at 100khz the smallest increase step is  17kz<>26kz    //  dutycycle 36,5%
at 254khz the smallest decrease step is  86kz<     //  dutycycle 15,8%

the frequency is stable with cristal precision! <1%

there is a lower frequency noise on the voltage level of the output pulses but it can be reduced adding more capacitors to the arduino voltage line i guess it could increase the frequency stability even further


the code:

// -----
// InterruptRotator.ino - Example for the RotaryEncoder library.
// This class is implemented for use with the Arduino environment.

// -----because of the limited range the lowest freq that can be generated with delayMicrosecond function is 30Hz but using normal delay it can be much lower perhaps 0,03hz

//the highest is 254khz

//freq adjust

//at 100hz  the smallest increase step is 0,02hz    //  dutycycle49,9%
//at 1khz   the smallest increase step is 2<>2hz   //  dutycycle  49,8%
//at 10khz the smallest increase step is 185<>200hz   //  dutycycle   48,6%
//at 100khz the smallest increase step is  17kz<>26kz    //  dutycycle 36,5%
//at 254khz the smallest decrease step is  86kz<     //  dutycycle 15,8%

//the frequency is stable with cristal precision! <1%

//i used This example that checks the state of the rotary encoder in the loop() function.
// The current position is printed on output when changed.

// Hardware setup:
// Attach a rotary encoder with output pins to A2 and A3.and switch to pin 3 to trigger interrupt1 added a small debounce capacitor from this pin to ground
// The common contact should be attached to ground.

#include <RotaryEncoder.h>

unsigned int range=100;
int swt=3;
unsigned int pos = 0;
unsigned int microdelay;

RotaryEncoder encoder(A2, A3);// Setup a RoraryEncoder for pins A2 and A3:

void setup()
{
DDRB |= 0B00100000; // activate pin13
cli();
TIMSK0 &= ~(1 << TOIE0);  // disable timer (no millis)
sei();

pinMode(swt, INPUT_PULLUP);
attachInterrupt(1,swtch,FALLING);  // pin3
Serial.begin(57600);
Serial.println("Arduino Frequency Generator with RotaryEncoder library.");
// You may have to modify the next 2 lines if using other pins than A2 and A3
PCICR |= (1 << PCIE1);    // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // This enables the interrupt for pin 2 and 3 of Port C.
}


// The Interrupt Service Routine for Pin Change Interrupt 1
// This routine will only be called on any signal change on A2 and A3: exactly where we need to check.
ISR(PCINT1_vect) {
  encoder.tick(); // just call tick() to check the state.
}

void loop()
{
  unsigned int newPos = encoder.getPosition();
  if (pos != newPos) {
  // Serial.println(newPos);
   Serial.println(microdelay);// Read the current position of the encoder and print out when changed.

 if ((newPos > pos)&& ((microdelay+range) <= 16300))  {
  microdelay= microdelay + range;
  }else if ((newPos<pos) && ((microdelay-range) >= 1)&& (microdelay-range)<=16300){
    microdelay= microdelay - range;
  }
     pos = newPos;
  }

microdelay= constrain((microdelay),1,16300);
PORTB |= 0B00100000;   //pin 13  on
   delayMicroseconds(microdelay);
PORTB &= 0B11011111;   //pin 13  off
   delayMicroseconds(microdelay);


       
  }
void swtch (){
 
    if (digitalRead(swt)== LOW)range=range*10;

 if (range > 100) range=1;
Serial.println (range);
  }

« Last Edit: August 21, 2018, 04:00:44 am by sebosfato »

Offline Login to see usernames

  • Global Moderator
  • Hero member
  • ****
  • Posts: 3607
Re: Arduino Analog Instruments
« Reply #17 on: August 21, 2018, 03:55:30 am »
just missing the save function to have the last frequency automatically recall

i dont think it will work on esp chips but probably will work on any arduino board

i´m using arduino nano 328/p processor to upload i have to select on arduino ide the nano board and set it as old boot loader since mine is a china one probably..


Offline Login to see usernames

  • Global Moderator
  • Hero member
  • ****
  • Posts: 3607
Re: Arduino Analog Instruments
« Reply #18 on: August 21, 2018, 05:26:13 am »

i turned off serial port of the arduino

i tweeked a little to start at 10hz but this also reduced the max freq to 130khz because i had to use 3 delays to lower from 30 to 10 hz the steps also changed it could be improved using a float perhaps but is already good for what i need now that is just a clock output to mimic the rpm sensor.. this will trigger the other arduino injection system while i dont plug it to the car fox ex

i improved the rotary input pins so i can use a fix pack of wires  in right order

and reversed the action of the switch and added a range  so  it now dont really need the save function because it became very fast to find the desired frequency

the button basically set how fine is the adjust and at the same time as consequence limit the ranges making it easy to work without display

now it goes from

10-555hz
10-1.6khz
10-16khz
10-130kz

hope you enjoy

new code:

// -----
// InterruptRotator.ino - Example for the RotaryEncoder library.

// -----because of the limited range the lowest freq that can be generated with delayMicrosecond function is 30Hz but using normal delay it can be much lower perhaps 0,03hz

//the highest is 254khz

//freq adjust

//at 100hz  the smallest increase step is 0,02hz    //  dutycycle49,9%
//at 1khz   the smallest increase step is 2<>2hz   //  dutycycle  49,8%
//at 10khz the smallest increase step is 185<>200hz   //  dutycycle   48,6%
//at 100khz the smallest increase step is  17kz<>26kz    //  dutycycle 36,5%
//at 254khz the smallest decrease step is  86kz<     //  dutycycle 15,8%

//the frequency is stable with cristal precision! <1%

//i used This example that checks the state of the rotary encoder in the loop() function.
// The current position is printed on output when changed.

// Hardware setup:
// Attach a rotary encoder with output pins to A2 and A3.and switch to pin 3 to trigger interrupt1 added a small debounce capacitor from this pin to ground
// The common contact should be attached to ground.

#include <RotaryEncoder.h>

unsigned int range=1000;
int swt=3;
unsigned int pos = 0;
unsigned int microdelay=16300;

RotaryEncoder encoder(A3, A2);// Setup a RoraryEncoder for pins A2 and A3:

void setup()
{
DDRB |= 0B00100000; // activate pin13
cli();
TIMSK0 &= ~(1 << TOIE0);  // disable timer (no millis)
sei();

pinMode(swt, INPUT_PULLUP);
attachInterrupt(1,swtch,FALLING);  // pin3
//Serial.begin(57600);
//Serial.println("Arduino Frequency Generator with RotaryEncoder library.");
// You may have to modify the next 2 lines if using other pins than A2 and A3
PCICR |= (1 << PCIE1);    // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // This enables the interrupt for pin 2 and 3 of Port C.
}


// The Interrupt Service Routine for Pin Change Interrupt 1 but the pin 3 interrupt sill work
// This routine will only be called on any signal change on A2 and A3: exactly where we need to check.
ISR(PCINT1_vect) {
  encoder.tick(); // just call tick() to check the state.
}

void loop()
{
  unsigned int newPos = encoder.getPosition();
  if (pos != newPos) {
  // Serial.println(newPos);
   //Serial.println(microdelay);// Read the current position of the encoder and print out when changed.

 if ((newPos > pos)&& ((microdelay+range) <= 16300))  {
  microdelay= microdelay + range;
  }else if ((newPos<pos) && ((microdelay-range) >= 1)&& (microdelay-range)<=16300){
    microdelay= microdelay - range;
  }
     pos = newPos;
  }

microdelay= constrain((microdelay),1,16300);
PORTB |= 0B00100000;   //pin 13  on
   delayMicroseconds(microdelay);
    delayMicroseconds(microdelay);
     delayMicroseconds(microdelay);
PORTB &= 0B11011111;   //pin 13  off
   delayMicroseconds(microdelay);
    delayMicroseconds(microdelay); delayMicroseconds(microdelay);
    }
void swtch (){
if (digitalRead(swt)== LOW)range=range/10;
if (range <1) range=1000;
//Serial.println (range);
  }


Offline Login to see usernames

  • Global Moderator
  • Hero member
  • ****
  • Posts: 3607
Re: Arduino Analog Instruments
« Reply #19 on: September 07, 2018, 05:16:07 am »

Offline Login to see usernames

  • Global Moderator
  • Hero member
  • ****
  • Posts: 3607
Re: Arduino Analog Instruments
« Reply #20 on: September 24, 2019, 03:57:54 am »
oh luckly i had something here