Overunity.com Archives is Temporarily on Read Mode Only!



Free Energy will change the World - Free Energy will stop Climate Change - Free Energy will give us hope
and we will not surrender until free energy will be enabled all over the world, to power planes, cars, ships and trains.
Free energy will help the poor to become independent of needing expensive fuels.
So all in all Free energy will bring far more peace to the world than any other invention has already brought to the world.
Those beautiful words were written by Stefan Hartmann/Owner/Admin at overunity.com
Unfortunately now, Stefan Hartmann is very ill and He needs our help
Stefan wanted that I have all these massive data to get it back online
even being as ill as Stefan is, he transferred all databases and folders
that without his help, this Forum Archives would have never been published here
so, please, as the Webmaster and Creator of this Forum, I am asking that you help him
by making a donation on the Paypal Button above
Thanks to ALL for your help!!


Arduino signal generator

Started by ayeaye, October 27, 2016, 02:33:55 PM

Previous topic - Next topic

0 Members and 3 Guests are viewing this topic.

TinselKoala

Here are some examples. The numbered screenshots and the Serial Monitor window of the same number.

In the last one (45) I actually entered 2520000 for the frequency -- and look what the program gave me!

ayeaye

I don't know whether your scope is capable of 4 Hz, mine is not. So i tested 10 Hz, and it was correct, though i couldn't trigger it. I also tried 100 Hz and 200 Hz with various duty cycles, different from your results all was correct. So the problems you had, i couldn't reproduce.

I'm sorry, there is one bug though

period = int(clock / frequency0);

there, using int() is wrong, because the period can be more than the maximum int, instead a cast (unsigned long) should be used there. But this affects only frequencies below 8 Hz, and 300 to 500 Hz. So as it was, it worked only in the frequency ranges 8 Hz to 299 Hz, and 500 Hz to 8 MHz, again sorry for that. The code with that fixed

Quote#include <avr/sleep.h>

#define BUFSIZE 80

char buffer[BUFSIZE];

float getvalue(char *text)
{
   char ch;

   Serial.print(text);
   sprintf(buffer, "");
   while (strlen(buffer) < BUFSIZE - 1)
      if (Serial.available()) {
         ch = Serial.read();
         if (ch == '\n') break;
         sprintf(buffer, "%s%c", buffer, ch);
      }
   return atof(buffer);
}

void setup()
{
   Serial.begin(9600);
   pinMode(10, OUTPUT);
}

void loop()
{
   float frequency0, frequency1, duty0, duty1;
   unsigned long period, duty, clock;

   frequency0 = getvalue("Frequency? \n");
   duty0 = getvalue("Duty Cycle? \n");
   if (duty0 < 0) duty0 = 0;
   if (duty0 > 100) duty0 = 100;
   clock = 16000000l;
   if (frequency0 < 300.) clock = 250000l;
   period = (unsigned long) (clock / frequency0);
   if (period < 2) period = 2;
   if (period > 65000l) period = 65000l;
   frequency1 = (double) clock / period;
   duty = (unsigned long) (period * duty0 / 100);
   if (duty < 1) duty = 1;
   if (duty > period - 1) duty = period - 1;
   duty1 = duty * 100. / period;
   OCR1A = period - 1;
   OCR1B = duty - 1;
   /* Timer1 fast PWM mode */
   TCCR1A = _BV(WGM11) | _BV(WGM10) | _BV(COM1B1);
   if (frequency0 > 300.)
      /* No prescaling */
      TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
   else
      /* 64 prescaling */
      TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10) | _BV(CS11);
   Serial.print("Frequency ");
   Serial.print(frequency1);
   Serial.print(", Duty Cycle ");
   Serial.println(duty1);
   Serial.println();
   delay(100);
   while (!Serial.available()) {
      set_sleep_mode(SLEEP_MODE_IDLE);
      sleep_enable();
      sleep_mode();
      sleep_disable();
   }
   TCCR1A = _BV(WGM11) | _BV(WGM10) | _BV(COM1B1);
   TCCR1B = _BV(WGM13) | _BV(WGM12);   /* Timer stop */
   TCNT1 = 0;            /* Timer value 0 */
   digitalWrite(10, 0);         /* Output 0 */
   Serial.read();
}

MagnaProp

Quote from: ronotte on October 30, 2016, 11:52:10 AM
Hi all,

it could be interesting to know that it is possible to setup a single frequency precision oscillator (with high stability). It uses an Arduino uP to program via the internal I2C interface an oscillator IC like DS1077. In such a case it is only necessary to write a program on arduino to setup the internal programmable frequency divider (in DS1077 chip). After the write operation you can detach the DS1077 chip and use it for your application simple & elegant & easy...This is a professional generator to be used intead of 555 chip or similar. Frequency spans up to 100 MHz range. I used it to generate high precision low frequency square wave needed by a TMT project. In case you are interested I can publish the code.

Ciao
ronotte
Sounds interesting to me. Posting your code would be greatly appreciated.

ronotte

OK here you find a paper containing detailed info about DS1077 programming and a practical code that is still in use...hence fully debugged. The project is dated 2014 and has been tested on Arduino Due uP board. I think that it could run easily on all Arduino family: just check the I2C pin availability.
The code is emebedded with debugging lines very useful to have a direct view (on the serial console) of what is happening!.

ayeaye

Quote from: TinselKoala on October 30, 2016, 11:01:04 PM
Here are some examples. The numbered screenshots and the Serial Monitor window of the same number.

In the last one (45) I actually entered 2520000 for the frequency -- and look what the program gave me!

Yes, i could now reproduce. The matter is, the frequencies were wrong when generating signal the first time after starting the serial monitor, they were right every next time. The order in which to assign the registers matters. What concerns the frequency 2520000 Hz then, because of the discreteness of the timer period, it is not able to provide an exact frequency with so high frequencies. Calculate, the period should be 16000000 / 2520000 = 6.349, but because period must be integer, it's 6. Then the frequency generated, is 16000000 / 6 = 2666666.7, as it was. This is the code with that fixed, it provided the right frequency the first time, every time i tested it.

Quote#include <avr/sleep.h>

#define BUFSIZE 80

char buffer[BUFSIZE];

float getvalue(char *text)
{
   char ch;

   Serial.println(text);
   sprintf(buffer, "");
   while (strlen(buffer) < BUFSIZE - 1)
      if (Serial.available()) {
         ch = Serial.read();
         if (ch == '\n') break;
         sprintf(buffer, "%s%c", buffer, ch);
      }
   return atof(buffer);
}

void setup()
{
   Serial.begin(9600);
   pinMode(10, OUTPUT);
}

void loop()
{
   float frequency, duty;
   unsigned long clock, period, pulsewidth;

   frequency = getvalue("Frequency?");
   duty = getvalue("Duty Cycle?");
   if (duty < 0) duty = 0;
   if (duty > 100) duty = 100;
   clock = 16000000l;
   if (frequency < 300.) clock = 250000l;
   period = (unsigned long) (clock / frequency);
   if (period < 2) period = 2;
   if (period > 65000l) period = 65000l;
   pulsewidth = (unsigned long) (period * duty / 100);
   if (pulsewidth < 1) pulsewidth = 1;
   if (pulsewidth > period - 1) pulsewidth = period - 1;
   /* Timer1 fast PWM mode */
   TCCR1A = _BV(WGM11) | _BV(WGM10) | _BV(COM1B1);
   if (frequency > 300.)
      /* No prescaling */
      TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
   else
      /* 64 prescaling */
      TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10) | _BV(CS11);
   OCR1A = period - 1;
   OCR1B = pulsewidth - 1;
   Serial.print("Frequency ");
   Serial.print((float) clock / period);
   Serial.print(", Duty Cycle ");
   Serial.println(pulsewidth * 100. / period);
   Serial.println();
   delay(100);
   while (!Serial.available()) {
      set_sleep_mode(SLEEP_MODE_IDLE);
      sleep_enable();
      sleep_mode();
      sleep_disable();
   }
   TCCR1A = _BV(WGM11) | _BV(WGM10) | _BV(COM1B1);
   TCCR1B = _BV(WGM13) | _BV(WGM12);   /* Timer stop */
   TCNT1 = 0;            /* Timer value 0 */
   digitalWrite(10, 0);         /* Output 0 */
   Serial.read();
}