Free Energy | searching for free energy and discussing free energy

Discussion board help and admin topics => Problems and Solutions for Accurate Measurements => Topic started by: ayeaye on October 27, 2016, 08:33:55 PM

Title: Arduino signal generator
Post by: ayeaye on October 27, 2016, 08:33:55 PM
I will put it here so that it will not be lost. This signal generator is capable of generating square wave with a varying duty cycle, from 4 Hz to 8 MHz, on the Arduino pin d10. The frequency comes from the Arduino 16 MHz clock frequency, which is generated by quartz, thus should be accurate. It was necessary to calibrate my oscilloscope. I used for that Arduino Nano, that i bought from eBay for $2.30, but the same must work for Arduino Uno, and several other varieties.
Quote
#include <avr/sleep.h>

#define BUFSIZE 80

char buffer[BUFSIZE];

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

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

   duty0 = 0;
   frequency0 = 0;
   Serial.print("Frequency? \n");
        sprintf(buffer, "");
        while (strlen(buffer) < BUFSIZE - 1)
                if (Serial.available()) {
                        ch = Serial.read();
                        if (ch == '\n') break;
                        sprintf(buffer, "%s%c", buffer, ch);
        }
        frequency0 = atof(buffer);
   Serial.print("Duty Cycle? \n");
        sprintf(buffer, "");
        while (strlen(buffer) < BUFSIZE - 1)
                if (Serial.available()) {
                        ch = Serial.read();
                        if (ch == '\n') break;
                        sprintf(buffer, "%s%c", buffer, ch);
        }
        duty0 = atof(buffer);
   if (duty0 < 0) duty0 = 0;
   if (duty0 > 100) duty0 = 100;
        clock = 16000000l;
        if (frequency0 < 300.) clock = 250000l;
          period = int(clock / frequency0);
          if (period < 2) period = 2;
        if (period > 65000) period = 65000;
          frequency1 = (double) clock / period;
          duty = int(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();
}
Title: Re: Arduino signal generator
Post by: Tink on October 27, 2016, 09:07:34 PM
Thanks! :D
I made a copy of it.
Title: Re: Arduino signal generator
Post by: MagnaProp on October 30, 2016, 12:42:19 AM
Thanks for posting the code!
Title: Re: Arduino signal generator
Post by: ronotte on October 30, 2016, 04:52:10 PM
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
Title: Re: Arduino signal generator
Post by: TinselKoala on October 31, 2016, 03:38:57 AM
I will put it here so that it will not be lost. This signal generator is capable of generating square wave with a varying duty cycle, from 4 Hz to 8 MHz, on the Arduino pin d10. The frequency comes from the Arduino 16 MHz clock frequency, which is generated by quartz, thus should be accurate. It was necessary to calibrate my oscilloscope. I used for that Arduino Nano, that i bought from eBay for $2.30, but the same must work for Arduino Uno, and several other varieties.

I tried it on a genuine Italian-made UNO R3. The code compiles but with several "warnings" that don't cause the compiler to stop.
I couldn't get it to work at first, it would simply hang after printing "frequency" to the serial monitor. So I discovered that the Serial Monitor "send" needs to end with a CR or CR/LF rather than just the plain number string. This is a selectable option in the Arduino IDE Serial Monitor. So once I selected "CR" and sent, say, "1000000" it replied with "duty cycle" and so I put in "50" and it worked, sent a pretty nice square wave to the oscilloscope.
BUT--- it did not work properly at low frequencies, giving strange results. I didn't explore just where the strange results started, but it certainly got weird when under 10 kHz. Sometimes the Serial Monitor string reported numbers that I didn't enter as freq and duty cycle, and often the reported numbers did not agree with the resulting signal as shown on the scope. At really low frequencies like 4Hz or 10Hz it did not produce oscillations at all, the output signal just stayed high.
But at higher frequencies it worked fine and the scope showed it to be accurate in terms of duty cycle and frequency.
Title: Re: Arduino signal generator
Post by: TinselKoala on October 31, 2016, 04:01:04 AM
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!
Title: Re: Arduino signal generator
Post by: ayeaye on October 31, 2016, 06:23:23 AM
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();
}
Title: Re: Arduino signal generator
Post by: MagnaProp on October 31, 2016, 07:25:08 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.
Title: Re: Arduino signal generator
Post by: ronotte on October 31, 2016, 11:35:13 AM
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!.
Title: Re: Arduino signal generator
Post by: ayeaye on October 31, 2016, 09:15:28 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();
}
Title: Re: Arduino signal generator
Post by: TinselKoala on November 01, 2016, 01:52:59 AM
You still have quite a few compiler warning messages. To see them in your IDE, select File>Preferences then check the "Show verbose output during compilation" box. They don't prevent a successful compile but they may be causing problems in how the sketch actually works.

I'll be testing this new version later on this evening. Thanks for your good work!
Title: Re: Arduino signal generator
Post by: Magluvin on November 01, 2016, 02:24:05 AM
This is a tiny oscope with arbitrary wave form gen up to 44khz analog and 1mbps max. Bought one a few years ago. This can interface with pc with gabos software download on that page. the make larger ones also as the screen on this is too small to strain your eyes on but the pc interface software works pretty good.
http://www.gabotronics.com/development-boards/xmega-xprotolab.htm (http://www.gabotronics.com/development-boards/xmega-xprotolab.htm)
$49

Mags
Title: Re: Arduino signal generator
Post by: TinselKoala on November 01, 2016, 03:58:34 AM
OK, I've done some testing of the new code. It does work better, at least at low frequencies.

But there is still some problem. At higher frequencies it does not do the duty cycle correctly. For example I input "8000000" for frequency and "33" for duty cycle and it gives me a 50 percent duty cycle. Or, if I don't reset the Arduino and put in 8000000 and 33 as a second setting, it gives me 125000 and 50. If I reset and put in 2520000 and 33, it gives me Frequency 2666666.75, Duty Cycle 16.67 .

The signal sent to the scope agrees with the Serial Monitor, but the program often gives me something other than what I put in as freq and duty cycle. Also it behaves differently if I reset the arduino before a new setting, than it does if I do not reset the arduino before a new setting.

But at least it oscillates at low frequencies now.
Title: Re: Arduino signal generator
Post by: ayeaye on November 01, 2016, 05:19:50 AM
For example I input "8000000" for frequency and "33" for duty cycle and it gives me a 50 percent duty cycle. Or, if I don't reset the Arduino and put in 8000000 and 33 as a second setting, it gives me 125000 and 50.

I'm afraid that i cannot reproduce again. I tested it without oscilloscope. I copied the exact code from here, compiled it, uploaded to the Arduino. Started the serial monitor, entered frequency 8000000 and duty cycle 33. It showed frequency 8000000 and duty cycle 50. Then i again entered the frequency 8000000 and duty cycle 33, without restarting the serial monitor, and it again showed frequency 8000000 and duty cycle 50, not frequency 125000 and duty cycle 50 as you said. So i could not reproduce it behaving differently when resetting and when not resetting.

What concerns the program giving something other than put in, then one reason why it certainly happens is because it is limited by discreteness. Like with the frequency 8000000, the duty cycle can only be 50, because with the Arduino clock frequency 16 MHz. the timer can only go two steps. With the frequency 2520000 and duty cycle 33, the pulse width has to be integer. The period as integer is 6, and 33 percent of it when truncated is 1, which is 16.7% of 6. It is not good that it is truncated and not rounded, but this is a simple program.

Thank you for testing.
Title: Re: Arduino signal generator
Post by: verpies on November 01, 2016, 10:19:33 AM
At higher frequencies it does not do the duty cycle correctly. For example I input "8000000" for frequency and "33" for duty cycle and it gives me a 50 percent duty cycle.
Of course because the 16MHz Arduino clock is not capable of providing more than 50/50 precision at 8MHz output.
Title: Re: Arduino signal generator
Post by: ayeaye on November 01, 2016, 09:28:37 PM
Ok, now it rounds, and is a bit shorter, too.

Quote
#include <avr/sleep.h>

#define BUFSIZE 60

float getvalue(const char *text)
{
   char buffer[BUFSIZE], ch;

   Serial.println(text);
   for (sprintf(buffer, ""); strlen(buffer) < BUFSIZE - 1;)
      if (Serial.available()) {
         if ((ch = Serial.read()) == '\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?");
   clock = frequency > 300. ? 16000000l : 250000l;
   period = (unsigned long) (clock / frequency + 0.5);
   if (period < 2) period = 2;
   if (period > 65000l) period = 65000l;
   pulsewidth = (unsigned long) (period * duty / 100 + 0.5);
   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();
}
Title: Re: Arduino signal generator
Post by: ayeaye on November 03, 2016, 12:13:13 AM
Ok, let's make a small change, to get rid of that nasty warning. It evidently worked, and corresponded to the C/C++ standards too, but when Arduino and gnu perhaps, has such requirements about sprintf, then let it have that. The rest of the warnings there were about the Arduino system code, about its serial interface, like an unused variable there, which in no way could been caused by my code. When compiling the second time there are no warnings, it doesn't show them more, because these are not relevant to the compiled code.

Quote
#include <avr/sleep.h>

#define BUFSIZE 60

float getvalue(const char *text)
{
   char buffer[BUFSIZE], ch;

   Serial.println(text);
   for (sprintf(buffer, "%c", '\0'); strlen(buffer) < BUFSIZE - 1;)
      if (Serial.available()) {
         if ((ch = Serial.read()) == '\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?");
   clock = frequency > 300. ? 16000000l : 250000l;
   period = (unsigned long) (clock / frequency + 0.5);
   if (period < 2) period = 2;
   if (period > 65000l) period = 65000l;
   pulsewidth = (unsigned long) (period * duty / 100 + 0.5);
   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();
}
Title: Re: Arduino signal generator
Post by: Magluvin on November 03, 2016, 06:34:32 AM
Found one of these that can be controlled by an arduino

http://www.analog.com/en/products/rf-microwave/direct-digital-synthesis/ad9833.html#product-overview

Mags
Title: Re: Arduino signal generator
Post by: ayeaye on November 06, 2016, 05:19:52 AM
Yes it's, quite simple. Yet i put it here, because in spite that it's simple, one should have it when one needs it. Signal generator is in fact the only thing i really need Arduino for, so far. Like all i needed for calibrating my oscilloscope, was a multimeter, and a square wave signal generator. Arduino Nano costs in ebay $2.20 with shipping, so makes sense to have it even when using it only as a signal generator. The only problem, it needs a different usb cable than the micro usb cable used for most smartphones and cameras today. It may be used for many special purposes when the need may be, like its analog comparator is fast and enables to measure a changing signals in quite many ways.

The cheaper option may be the Digispark Attiny85 board, which costs only $1.20 in ebay, and is almost the same, except that it has less pins, less memory, and only two 8 bit timers. So the signal generator code has to be somewhat modified for that, though not much, and there is not so much precision for a duty cycle. The problem with that though, is that it uses an internal 16 MHz clock, not an external quartz resonator like Arduino Nano. When using it with usb, the clock is calibrated by usb, and said to have a 1% precision, when the temperature doesn't change much that is, but when using without usb, the precision is only 10%, unless separately calibrated every time. This may be good enough for some purposes but it is not good enough for some measuring.
Title: Re: Arduino signal generator
Post by: Magluvin on November 06, 2016, 07:17:38 AM
Just alternative suggestions. Had a TRS-80 color computer back in the days. I believe it was .88mhz cpu and could be over clocked some, like just below or over 1mhz. The processor had to handle all the graphics, of which would take away valuable computing power. Then my brother got a Vic-20 when it came out and it at least had sprites, in which left the cpu more time to do other things while still producing better graphics. Then I got into the Amiga 500, kinda toward the end of their life. But the graphics were incredible, mostly due to separate graphics chips. So now the cpu is able to spend all its time doing other things than producing the graphics display functions.

So I lean toward independent driver circuits when using the arduino so the arduino isnt stressed with avoiding possible little glitches of the desired output when the processor has workloads or even taking time to accept input to adjust the outputs. Anyway

Mags
Title: Re: Arduino signal generator
Post by: ayeaye on November 06, 2016, 06:32:37 PM
My Arduino Nano. Costs $2.26 with shipping when bought from ebay  http://www.ebay.com/itm/MINI-USB-Nano-V3-0-ATmega328P-CH340G-5V-16M-Micro-controller-board-For-Arduino-N-/141975930194?hash=item210e6cc552:g:e58AAOSwpDdVL5yR (http://www.ebay.com/itm/MINI-USB-Nano-V3-0-ATmega328P-CH340G-5V-16M-Micro-controller-board-For-Arduino-N-/141975930194?hash=item210e6cc552:g:e58AAOSwpDdVL5yR) . Because it's small, it comes quite fast, and it comes directly to your mailbox, so it's easy to get. If one is very rich, one may think about buying that one for $3.78 with shipping, which also comes with the right usb cable  http://www.ebay.com/itm/ATMEGA328P-FT232RL-FTDI-Micro-controller-Module-for-Arduino-Nano-V3-0-With-Cable-/381801276448?hash=item58e5212420:g:kVMAAOSwHnFVybGk (http://www.ebay.com/itm/ATMEGA328P-FT232RL-FTDI-Micro-controller-Module-for-Arduino-Nano-V3-0-With-Cable-/381801276448?hash=item58e5212420:g:kVMAAOSwHnFVybGk) . Though if one happens to have some very old digital camera somewhere or something, then its usb cable is exactly the right one.
Title: Re: Arduino signal generator
Post by: ayeaye on November 06, 2016, 08:45:34 PM
The Digispark ATtiny85 board costs in ebay $1.52 with shipping  http://www.ebay.com/itm/Digispark-ATTINY85-General-Micro-USB-Development-Board-For-Arduino-New-WA-/281921984524?hash=item41a3dc180c:g:lMEAAOSwXshWqy3A (http://www.ebay.com/itm/Digispark-ATTINY85-General-Micro-USB-Development-Board-For-Arduino-New-WA-/281921984524?hash=item41a3dc180c:g:lMEAAOSwXshWqy3A) . A link to their license https://creativecommons.org/licenses/by-sa/3.0 (https://creativecommons.org/licenses/by-sa/3.0) . That one has really not much more on it, bout the ATtiny85 integrated circuit, and a voltage regulator, which is also unnecessary when powered by usb. The only thing is that for using a separate ATtiny85 like that, a bootloader has to be written into it, which needs a programmator. This one goes to the standard usb socket, there is also a variety with a micro usb socket on it, but that one is somewhat more expensive. Can be used with the Arduino software, but read above about the limitations of this one.
Title: Re: Arduino signal generator
Post by: madddann on May 02, 2018, 01:26:41 AM
Hello everyone!

I know this thread is old, but since the topic is right, I will post here.
I'm looking for some arduino code, or someone that would be so kind and write it for me and whoever may need it next.
What I'm looking for is a two phase PWM signal generator with:
-variable frequency from 1Hz (or at least around 5Hz) up to whatever is possible - reasonable  (adjustable with pot.)
-variable duty cycle from 1% to 100%, resolution the more the better (adjustable with pot.)
-two outputs shifted (delayed) for half the total period (180°), (not inverted - same signal on both channels only shifted)

Well, that's it. I would try to modify the last code posted by user ayeaye if I only had a clue what is written inthere  :D .
I have an arduino nano 328p, V3.

I'm experimenting with a Figuera type setup, that's what I need the two phase signal generator for.
I rarely post, so I'll understand if this goes unnoticed, but this is the only time in 10 years that I'm asking for something, so please, If someone with the right skills is reading this and willing to help out, I will be very gratefull.

Dann

Title: Re: Arduino signal generator
Post by: kEhYo77 on May 02, 2018, 06:40:37 AM
Reposting this from Figuera thread.

All you need is:[/size]1. ONE 10k/100k Ohm potentiometer. Connect the middle leg to Arduino's "A0" analog input. The other two legs of the pot goes to +5V and GND on Arduino.2. TWO Logic Level MOSFET transistors to do the switching (Logic level - like in IRL series -  means that a mosfet is in a conduction saturation state at just +5V put to its gate). Connect the Gate of one mosfet to "Pin 3" and the others' gate to "Pin 11". Sources go to the "GND" of the Arduino board.3. Connect +(positive) from a battery to both "North" & "South" coils and their ends to both drains in the two mosfets and -(negative) to the Arduino's "GND" close to the Source legs of mosfets.4. Connect fast shottky diodes across each coil to do the freewheeling of current.Program description:Arduino is generating a digital signal at 32 kHz frequency using 2 PWM outputs. The value for each "sample" is taken from the sine table. There are 256 values of resolution for the "shape" of the sine wave and 256 values of amplitude. You can change phase shift by changing "offset" variable. Potentiometer allows to set the analog frequency from 0 to 1023 Hz at 1 Hz resolution...NOW copy the code below to Arduino IDE window and save it to the microconroller and HERE YOU GO! 

Quote
/* CLEMENTE FIGUERAS GENERADOR DRIVER
 * modification by kEhYo77
 *
 * Thanks must be given to Martin Nawrath for the developement of the original code to generate a sine wave using PWM and a LPF.
 * http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/ (http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/)
*/




#include "avr/pgmspace.h" //Store data in flash (program) memory instead of SRAM




// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM  prog_uchar sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124




};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) //define a bit to have the properties of a clear bit operator
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator




int PWM1 = 11; //PWM1 output, phase 1
int PWM2 = 3; //PWM2 ouput, phase 2
int offset = 127; //offset is 180 degrees out of phase with the other phase




double dfreq;
const double refclk=31376.6;      // measured output frequency
int apin0 = 10;




// variables used inside interrupt service declared as voilatile
volatile byte current_count;              // Keep track of where the current count is in sine 256 array
volatile unsigned long phase_accumulator;   // pahse accumulator
volatile unsigned long tword_m;  // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.




void setup()
{
  pinMode(PWM1, OUTPUT);      //sets the digital pin as output
  pinMode(PWM2, OUTPUT);      //sets the digital pin as output
  Setup_timer2();
 
  //Disable Timer 1 interrupt to avoid any timing delays
  cbi (TIMSK0,TOIE0);              //disable Timer0 !!! delay() is now not available
  sbi (TIMSK2,TOIE2);              //enable Timer2 Interrupt




  dfreq=10.0;                    //initial output frequency = 1000.o Hz
  tword_m=pow(2,32)*dfreq/refclk;  //calulate DDS new tuning word
 
  // running analog pot input with high speed clock (set prescale to 16)
  bitClear(ADCSRA,ADPS0);
  bitClear(ADCSRA,ADPS1);
  bitSet(ADCSRA,ADPS2);




}
void loop()
{
        apin0=analogRead(0);             //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 1.023kHz
        if(dfreq != apin0){
          tword_m=pow(2,32)*dfreq/refclk;  //Calulate DDS new tuning word
          dfreq=apin0;
        }
}




//Timer 2 setup
//Set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer2()
{
  // Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);




  // Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0);  // clear Compare Match
  sbi (TCCR2A, COM2A1);
  cbi (TCCR2A, COM2B0);
  sbi (TCCR2A, COM2B1);
 
  // Mode 1  / Phase Correct PWM
  sbi (TCCR2B, WGM20); 
  cbi (TCCR2B, WGM21);
  cbi (TCCR2B, WGM22);
}








//Timer2 Interrupt Service at 31372,550 KHz = 32uSec
//This is the timebase REFCLOCK for the DDS generator
//FOUT = (M (REFCLK)) / (2 exp 32)
//Runtime : 8 microseconds
ISR(TIMER2_OVF_vect)
{
  phase_accumulator=phase_accumulator+tword_m; //Adds tuning M word to previoud phase accumulator. refer to DDS_calculator (from Martin Nawrath) for explination.
  current_count=phase_accumulator >> 24;     // use upper 8 bits of phase_accumulator as frequency information                     
 
  OCR2A = pgm_read_byte_near(sine256 + current_count); // read value fron ROM sine table and send to PWM
  OCR2B = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset)); // read value fron ROM sine table and send to PWM, 180 Degree out of phase of PWM1
}

http://www.youtube.com/watch?v=hC70s3tYaGs&hd=1 (http://www.youtube.com/watch?v=hC70s3tYaGs&hd=1)
Title: Re: Arduino signal generator
Post by: madddann on May 02, 2018, 11:37:04 AM
Wow! Thank you kEhYo77, now i remember seeing your video... long time since then...
The code you posted will sure come handy in the future, but what I need right now is much simpler, I knew I forgot to mention something.

What I'm asking for is just two square wave signals offset by half the period (180°), with adjustable on time and frequency, thats all.

Like the two signals "PWM1" and "PWM3" on this picture: https://batchloaf.files.wordpress.com/2015/03/four_phase_pwm.png

I'm doing Figuera experiments "Tesla style" - creating two resonant tanks with oposite signals - wich the electromagnets are a part of.
I'm sure you could try this also on your setup (from the video)... just add capacitors to the coils (electromagnets) and excite the hell out of it  ;D .

Thanks again! If you or anyone else would put together the code for the two square wave signals, that would be great.

Dann


Title: Re: Arduino signal generator
Post by: kEhYo77 on May 02, 2018, 11:58:57 AM
Maybe just this.
Title: Re: Arduino signal generator
Post by: madddann on May 02, 2018, 06:44:16 PM
Well, yes that chip would be perfect for what I need, but I just spent the last 3 hours trying to get it to work with no success.
I have only one chip and that one may be defective. A few times I could see some signal for a fraction of a second when connecting the supply voltage. I could also see the ramp waveform on the capacitor, but other than that there were no other pulsed signals on any other pin.
Did you test your schematic? Was it working for you?
Thanks again kEhYo77, if you happen to think of any alternatives, I'm all ears.

Dann
Title: Re: Arduino signal generator
Post by: kEhYo77 on May 02, 2018, 08:54:32 PM
Yes. I have tested it and it is working for me.
Title: Re: Arduino signal generator
Post by: gyulasun on May 02, 2018, 11:29:16 PM
Well, yes that chip would be perfect for what I need, but I just spent the last 3 hours trying to get it to work with no success.
I have only one chip and that one may be defective. A few times I could see some signal for a fraction of a second when connecting the supply voltage. I could also see the ramp waveform on the capacitor, but other than that there were no other pulsed signals on any other pin.
Did you test your schematic? Was it working for you?
Thanks again kEhYo77, if you happen to think of any alternatives, I'm all ears.

Dann

Hi,

Sorry to chime in,  this TL494 circuit was a topic on this forum, and member itsu for instance
built the circuit and it also worked for him, see this link with his schematics:
http://overunity.com/12736/kapanadze-cousin-dally-free-energy/msg507286/#msg507286 (http://overunity.com/12736/kapanadze-cousin-dally-free-energy/msg507286/#msg507286)

His circuit is almost the same: the difference is he connected pins 14 to pin 15 and grounded
pin 16,  and he added decoupling capacitors as you can see.
I am not saying the schematic by kEhYo77 is not working, perhaps the trick is the use of the
filter capacitors across the 5V reference and ground and also across the main supply input and ground.
IT would be worth trying these changes.

And here is yet another variant where the dead time can also be varied, besides duty cycle and
frequency:  http://overunity.com/12736/kapanadze-cousin-dally-free-energy/msg502495/#msg502495 (http://overunity.com/12736/kapanadze-cousin-dally-free-energy/msg502495/#msg502495)
Of course your TL494 might be defective.

Gyula
Title: Re: Arduino signal generator
Post by: madddann on May 03, 2018, 10:21:03 PM
Hello Gyula!

Don't be sorry, any helpful input is well appreciated. I put together the circuit from the schematic by Itsu an it works, but the output signals are kinda jumpy at times, like when I turn the duty cycle pot to a certain value (the pots are new). It's also starnge that when the duty cycle is in the region near max. everything looks good, but when I turn the pot down slowly and evenly, the duty cycle on one output channel (I think pin 9) jumps to minimum and stays there until I turn the pot back up near max. I also played with separate duty and dead time circuit but it's the same story. Tryed two equivalent chips (KA7500B) and still all the same.

The schematic from kEhYo77 works only if I connect pins 1 and 16 to ground.

But maybe I shoudn't rely on cheap chinese protoboards for testing circuits.

Thanks guys!


Dann

Title: Re: Arduino signal generator
Post by: gyulasun on May 04, 2018, 12:33:57 AM
Hi Dann,

Good you managed to make it work, albeit with that unwanted issues.  Perhaps a 'dead bug' construction
instead of the protoboard may cure the problem.
You can think of spurious oscillations due to not enough decoupling on input pins and / or the 5V reference pin.
See this motor speed control circuit based on TL494 where the wiper of duty cycle control pot is shunted by
a 220 uF, rather unusual:  http://www.nawattakam.com/talk/index.php?topic=784.0  Also, the pin connections
around the duty cycle circuit are different from the schematics shown in this forum hence from what you built. 
Maybe it would be worth rewire your board for the changes because pin 4 (dead time control) is grounded
which is your duty cycle control input at present and receives varying DC voltage from the wiper of the potmeter.
The motor speed control circuit in the above link gives almost 100% duty control by combining the two out of phase
outputs for the motor via the two power MOSFETs, originally the TL494 gives duty control from 1% to 45% only, if I
understand correctly.  Good luck.

Gyula
Title: Re: Arduino signal generator
Post by: madddann on May 04, 2018, 11:03:01 PM
Hi Gyula.

Thanks for that schematic, I fiddled with the circuit some more time and got it to work (above certain frequency). It seems that below 30kHz the duty cycle anomaly on one of the outputs starts to happen.
Anyway I just realized this chip will not go below 1kHz, so it doesn't help me with what I'm experimenting right now.
I also have an SG3525, but the lowest it will go is 100Hz, which is still higher than I would like.

So now I came full circle, and learned something useful along the way.


@all.

Now back to the arduino plan.
I'll write down the specs needed here again:

-two phase PWM square wave generator
-variable frequency from 1Hz (or at least around 5Hz) up to whatever is possible - reasonable  (adjustable with pot.)
-variable duty cycle from 1% to 100%, resolution the more the better (adjustable with pot.)
-two outputs shifted (delayed) for half the total period (180°), (not inverted - same signal on both channels only shifted) like the signals PWM1 and PWM3 here: https://batchloaf.files.wordpress.com/2015/03/four_phase_pwm.png (https://batchloaf.files.wordpress.com/2015/03/four_phase_pwm.png)

I have an arduino nano 328p, V3.

Anyone that enjoys fiddelin with code Is welcome  :) .

Maybe somewhere on the net already exsists some code for a 4 phase or 6 phase PWM controller with adjustable frequency...
If anyone happens to know about it please post it here.
Any help is appreciated.

Thanks everyone!
Title: Re: Arduino signal generator
Post by: gyulasun on May 05, 2018, 09:07:43 PM
Hi Dann,

I understand your aim to use your Arduino chip. Hopefully the needed specifications you set out can be
achieved either by your chip or by a PIC chip (microcontroller).

Yet, I would again like to refer to an 'analog' way of producing shifted pulses. You surely heard about
modified sine wave inverters, these are basically DC to AC power converters and their output waveforms
try to mimic the needed sine wave shape as close as possible. And this involves the producing of shifted
pulses first. See such circuit here, with scope shot on the waveform you would need:
https://www.homemade-circuits.com/how-to-build-simplest-modified-sine/ (https://www.homemade-circuits.com/how-to-build-simplest-modified-sine/) 
Unfortunately, this circuit does not include duty cycle control.  It could be provided by using a dual monostable
multivibrator (say CD4538) which would stretch out or reduce the pulse width coming from IC2 (CD4017)
and you could control the pulse width by a double (stereo) potmeter or individually for the two channels.
Here is another circuit to produce the shifted pulses, with other than the CD4017:
http://www.instructables.com/id/Modified-Sine-Wave-Signal-Generator/ (http://www.instructables.com/id/Modified-Sine-Wave-Signal-Generator/)  but it does not have duty cycle control either.
 
Good luck.
Gyula
Title: Re: Arduino signal generator
Post by: madddann on May 06, 2018, 12:32:05 AM
Hi! Thanks for the suggestions Gyula.

I think I have some of those SN74LSxx chips and I also have a variable frequency PWM (555 + comparator) that I used before,
so I may come up with some mix that works. Will try to play tomorrow in multisim.

Today I got some help from someone close and we did program (just few lines of code) the arduino nano to output two PWM signals shifted by 180°, at a fixed frequency.
So I did play a bit with my figuera setup and noticed that variable phase shift would come also handy  ;D .
I also think that the mosfets are cutting off almost half (top section) of the resonant wave, so will have to replace them with ordinary transistors.
The problems pile up one after another, but hopefully the solutions will outmatch them.

On the arduino forum I found some discussion and code that would do what I need, but it's for arduino mega: https://forum.arduino.cc/index.php?topic=482903.0
Maybe I'll ask there for some help.

Dann


Title: Re: Arduino signal generator
Post by: kEhYo77 on May 07, 2018, 06:41:08 PM
YO!

I spent the whole weekend trying to figure this out and here it is!!!
3 controlling pots: Frequency / Duty / Range
Max operational frequency around 500 kHz
Min operational frequency around 1 Hz
The resolution of duty cycle goes down the higher you go up in given frequency range.


Enjoy!!!


Quote
// Dual pin PWM PUSH-PULL generator FOR Arduino UNO on pins 9&10
// by kEhYo77 2018


int user_cycles;
int user_duty;
int user_range;
int temp_cycles;
int temp_duty;
int temp_range;
int tuner;
unsigned long past = 0;


void set(int cycles, float duty) {
 
  char oldSREG;
 
  int dutyCycle = cycles * duty;
  if (dutyCycle < 6) {
    dutyCycle = 6; // Prevent duty cycle from being too short
  }

  oldSREG = SREG; // Save the registers
  cli(); // Disable interrupts for 16 bit register access
  ICR1 = cycles; // ICR1 is TOP in p & f correct pwm mode
  OCR1A = cycles-dutyCycle/2+1; //Pin 9 match
  OCR1B = dutyCycle/2-1; //Pin 10 match
 
  SREG = oldSREG; // Restore the registers
}


void setup() {
 
  pinMode(A0, INPUT); //analoque pot input Frequency
  pinMode(A1, INPUT); //analoque pot input DutyCycle
  pinMode(A2, INPUT); //analogue pot input Range
 
  bitClear(ADCSRA,ADPS0); //running analog pot input
  bitClear(ADCSRA,ADPS1); //with high speed clock
  bitSet(ADCSRA,ADPS2); //set prescaler to 16
   
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B


  TCCR1A = 0; //clear timer1 registers
  TCCR1B = 0;
  TCNT1 = 0;


  TCCR1A |= _BV(COM1A1) | _BV(COM1A0);
  //Output A. Set OC1A/OC1B on Compare Match,
  //Clear OC1A/OC1B at BOTTOM (inverting mode)


  TCCR1A |= _BV(COM1B1);
  //Output B. Clear OC1A/OC1B on Compare Match when up-counting.
  //Set OC1A/OC1B on Compare Match when down-counting.


  TCCR1B |= _BV(WGM13); //PWM Phase Correcrt mode 10 to ICR1
  TCCR1A |= _BV(WGM11); //WGM13:WGM11 set 1010
  TCCR1B |= _BV(CS10); //set prescaler 1
}


void loop() {
  if ((millis() - past) >= 500) { //read pots every half second
  temp_cycles = analogRead(A0);
  temp_duty = analogRead(A1);
  temp_range = analogRead(A2);
  past = millis();
   
  if (temp_cycles != user_cycles || temp_duty != user_duty) {
    user_cycles = temp_cycles;
    user_duty = temp_duty;
    set(user_cycles * tuner, user_duty / 1024.0);
  }


  if (temp_range != user_range) {
  if (temp_range <= 250) { TCCR1B |= (1<<CS10); TCCR1B &= ~((1<<CS11) | (1<<CS12)); tuner = 1; } // prescaler 1 ( 8 kHz - 300 kHz )
  if (temp_range > 250 & temp_range <= 500) { TCCR1B |= _BV(CS11); TCCR1B &= ~((1<<CS10) | (1<<CS12)); tuner = 8; } //prescaler 8 ( 120 Hz - 40 kHz )
  if (temp_range > 500 & temp_range <= 750) { TCCR1B |= _BV(CS10) | _BV(CS11); TCCR1B &= ~(1<<CS12); tuner = 16; } //prescaler 64 ( 4 Hz - 1 kHz )
  if (temp_range > 750 & temp_range <= 1024) { TCCR1B |= _BV(CS12); TCCR1B &= ~((1<<CS10) | (1<<CS11));  tuner = 32; } //prescaler 256 ( 1 Hz - 60 Hz )
  user_range = temp_range;
  }


  }
}
Title: Re: Arduino signal generator
Post by: forest on May 07, 2018, 08:31:40 PM
Beautiful! Could you post two outputs on the same plane , because it looks a bit shifted in phase (not pure 180 degrees) ?
Title: Re: Arduino signal generator
Post by: kEhYo77 on May 07, 2018, 08:33:22 PM
It is 100% 180 deg. shifted phase corrected mode.
The output looks distorted only at this max frequency.
Title: Re: Arduino signal generator
Post by: forest on May 07, 2018, 08:46:05 PM
I'm interested if there is possibility to change the slope rising time especially to make it more sinusoidal :-) by any eternal filter maybe ?
Title: Re: Arduino signal generator
Post by: kEhYo77 on May 07, 2018, 08:53:36 PM
I am afraid not. This method uses hardware timer registers to do the magic using mainly hardware and no software.
You can try to adapt my previously posted code for Figuera in this thread where I use sine table values.
You can "draw" in this table any shape you want.
Title: Re: Arduino signal generator
Post by: TinselKoala on May 08, 2018, 05:38:03 AM
Nice work!

Tested and verified to work with Arduino UNO R3, so it will most likely work on all members of that family (nano, promini, etc.). I have not yet tested it on a MEGA.

Probably a good idea to specify that all 3 pots should be same value. 10K is good, 50k is probably better. The pots are effectively in parallel so they interact somewhat.

It might be interesting to eliminate the pots and just use the serial monitor to send values instead. But since this sketch depends on having the actual inputs at analog pins A0, A1 and A2 to work, instead of just arbitrary variable values, it might take a little fiddling to enable serial functionality.

Title: Re: Arduino signal generator
Post by: kEhYo77 on May 08, 2018, 04:53:38 PM
This code should work on Mega but you have to change the OUTPUT pin numbers to 11 and 12 as 16bit counter Timer1 [/size]is assigned there differently.
I will improve on that code to make it work with an LCD/serial and a rotary encoder to automatically dial in desired frequency.
Another weekend off ;)
This one is fresh from the bakery and if someone wants to modify it feel free.


Title: Re: Arduino signal generator
Post by: madddann on May 08, 2018, 07:12:18 PM
OMG kEhYo77, I'm speechless, thank you soo much, I saw this just now.

TK, thanks for testing.

Dann
Title: Re: Arduino signal generator
Post by: kEhYo77 on May 13, 2018, 03:18:20 PM
I came across this variable frequency! 3 phase! sine! generator code for Arduino UNO, hope you like it.


Quote
// 3 phase PWM sine
// (c) 2016 C. Masenas
// Modified from original DDS from:
// KHM 2009 /  Martin Nawrath


// table of 256 sine values / one sine period / stored in flash memory
PROGMEM const unsigned char sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124


};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
         
int testPin = 7;
int enablePin = 6 ;


volatile  float freq=1;
const float refclk=122.549  ;     //  16 MHz/510/256


// variables used inside interrupt service declared as voilatile
volatile unsigned long sigma;   // phase accumulator
volatile unsigned long delta;  // phase increment
byte phase0, phase1, phase2 ;


void setup()
{
  Serial.begin(9600);        // connect to the serial port
  Serial.println("DDS Test");


  pinMode(enablePin, OUTPUT);      // sets the digital pin as output
  pinMode(testPin, OUTPUT);      // sets the digital pin as output
  pinMode(9, OUTPUT);     // pin9= PWM  output / frequency output
  pinMode(10, OUTPUT);     // pin10= PWM  output / frequency output
  pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output


  Setup_timer2();
  Setup_timer1();
  digitalWrite(enablePin, HIGH);


// the waveform index is the highest 8 bits of sigma
// choose refclk as freq to increment the lsb of the 8 highest bits
//    for every call to the ISR of timer2 overflow
// the lsb of the 8 highest bits is 1<<24 (1LL<<24 for long integer literal)
  delta = (1LL<<24)*freq/refclk ; 
}
void loop(){
 
  changeFreq(20);
  delay(10000);
  changeFreq(25);
  delay(10000);
             
 }


void changeFreq(float _freq){
  cbi (TIMSK2,TOIE2);              // disable timer2 overflow detect
  freq = _freq;
  delta=(1LL<<24)*freq/refclk;  // update phase increment
  sbi (TIMSK2,TOIE2);              // enable timer2 overflow detect
}


//******************************************************************
// timer2 setup
// set prscaler to 1,  fast PWM
void Setup_timer2() {


// Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);  // set
  cbi (TCCR2B, CS21);  // clear
  cbi (TCCR2B, CS22);


  // Timer2 PWM Mode
  cbi (TCCR2A, COM2A0);  // clear OC2A on Compare Match, PWM pin 11
  sbi (TCCR2A, COM2A1);


  // set to fast PWM
  sbi (TCCR2A, WGM20);  // Mode 1, phase correct PWM
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);


  sbi (TIMSK2,TOIE2);              // enable overflow detect
 
}
// timer1 setup  (sets pins 9 and 10)
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer1() {


// Timer1 Clock Prescaler to : 1
  sbi (TCCR1B, CS10);
  cbi (TCCR1B, CS11);
  cbi (TCCR1B, CS12);


  // Timer1 PWM Mode set to Phase Correct PWM
  cbi (TCCR1A, COM1A0);  // clear OC1A on Compare Match, PWM pin 9
  sbi (TCCR1A, COM1A1);
  cbi (TCCR1A, COM1B0);  // clear OC1B on Compare Match, PWM pin 10
  sbi (TCCR1A, COM1B1);


  sbi (TCCR1A, WGM10);  // Mode 1  / phase correct PWM
  cbi (TCCR1A, WGM11);
  cbi (TCCR1B, WGM12);
  cbi (TCCR1B, WGM13);
}


//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// runtime : 8 microseconds ( inclusive push and pop)
// OC2A - pin 11
// OC1B - pin 10
// OC1A - pin 9
// https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
ISR(TIMER2_OVF_vect) {


  sbi(PORTD,testPin);         


  sigma=sigma+delta; // soft DDS, phase accu with 32 bits
  phase0=sigma >> 24;     // use upper 8 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
  phase1 = phase0 +85 ;
  phase2 = phase0 +170 ;


  OCR2A=pgm_read_byte_near(sine256 + phase0);  // pwm pin 11
  OCR1B=pgm_read_byte_near(sine256 + phase1);  // pwm pin 10
  OCR1A=pgm_read_byte_near(sine256 + phase2);  // pwm pin 9


  cbi(PORTD,testPin);           
 
}
Title: Re: Arduino signal generator (Teensy)
Post by: Reiyuki on May 14, 2018, 03:44:13 PM
Great thread, everyone. ;)


One issue I and others have run into is clock-rate.  At higher frequencies, many of the sketches posted lose granularity and become distorted.

Most Arduino run at 16mhz, but sketches using PWM or pulses are often only clean up to 50-200khz.

I've had good luck boosting this number by using higher clockrate Arduinos, specifically Teensy's:
https://www.pjrc.com/teensy/

The improvements are largely linear (sketches that become distorted at 100khz with 16mhz clock tend to reach 300khz with 48mhz clock.

Note: Some sketches (especially ones using interrupts) will need to be tweaked to work with the different chipset.  Also, many of the faster Teensy's are 3.3v and not 5v, so you may need to make changes elsewhere to accommodate.