Quater sine wave

Hello, I'm about to create a quarter sine wave. I would then like to run through this four times in total in order to generate a sine curve. I hope this will free up some space on the Arduino. Overall I was thinking of 1200 spots per quarter turn. Does anyone have an idea how I can program this?

you could generate an array containing sine wave values for output using a D toA converter or better still use a DDS chip

Example, amplitude of 127, offset by 128.

// The first quarter wave samples LUT
static const uint8_t wavelut[] = {
  0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
  0x98, 0x9b, 0x9e, 0xa2, 0xa5, 0xa7, 0xaa, 0xad,
  0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbe, 0xc1, 0xc4,
  0xc6, 0xc9, 0xcb, 0xce, 0xd0, 0xd3, 0xd5, 0xd7,
  0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8,
  0xea, 0xeb, 0xed, 0xee, 0xf0, 0xf1, 0xf3, 0xf4,
  0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfa, 0xfb, 0xfc,
  0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff
};
    // Samples count for quarter, half and full wave
    const uint8_t   qart = sizeof(wavelut) / sizeof(*wavelut);;
    const uint8_t   half = qart + qart;
    const uint16_t  full = half + half;
/**
  Get an instant wave sample

  @param idx the wave sample index
*/
uint8_t sample(uint8_t idx) {
  // Work on half wave
  uint8_t hIdx = idx & 0x7F;
  // Check if in second quarter wave
  if (hIdx >= qart)
    // Descending slope
    hIdx = half - hIdx - 1;
  // Get the value
  uint8_t result = wavelut[hIdx];
  // Check if in second half wave
  if (idx >= half)
    // Under X axis
    result = 0xFF - result;
  return result;
}

@jremington Nice, THX.

Do you have left anywhere the equation you used to generate the table values?

Abject curiosity and I see a long flat section - I know sin gets very low dv/dt.

My just now thoughtless attempt left a longer flat area, I'll keep working on it.

TIA

a7

float x = 0;
float y = 0;
const float pi = 3.14;
int z = 0;
float v = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  v = x * pi / 180;
  y = sin(v);
  z = y * 126;
  x = x + 1.3;

  if (x > 360) {
    //if (x > 90) {
    x = 0;
  }
  //dacWrite(25, z + 126);//ESP32
  Serial.println(z);
  //730
}
Season to taste...
  float dt=1./(4*64);
  float twoPI = 2*PI;
    for (j = 0; j < 64; j++) {
       float a = 128+127.0 * sin(twoPI *j * dt);
      Serial.println(round(a),HEX);
      }

@jremington THX!

I won't bother to share where I went wrong. :expressionless:

a7

When x goes past 360, the correction should not be to make it zero, rather you should subtract 360.

Also, where does 1.3 come from? This makes one cycle take 277 steps.

Why do you use 126 in several places?

PI is available, no need to use 3.14…

a7

1200 samples will likely take up much more space than the SIN() function. What are you using the sine values for?

I guess you could always use Bhaskara's sine approximation formula.

I generate a sine and a triangle signal, which I compare both with one vein. With the previous values I only get a frequency of 5kHz. I would like to get higher than 25kHz. And in order to get to 25kHz with the 16 values in the triangular signal, I need 8000 values in the sine signal. The Arduino micro is more than full with this. So my idea was to take only a quarter of the sine values and calculate the rest.

signed char S[1600]=
{};

//Dreiecksignal
int D[16]={};

ISR(TIMER1_COMPA_vect){         //Interrupt

//Signalvergleich
if (D[n] < val*S[m]) {          //Dreiecksignal kleiner als Sinussignal
bitSet(PORTC, 6);               //Pin 5 HIGH
}
else {                          //Dreiecksignal größer als Sinussignal
bitClear(PORTC, 6);             //Pin 5 LOW
}
if (D[n] < val*S[m]) {          //Dreiecksignal kleiner als Sinussignal
bitSet(PORTD, 7);               //Pin 6 HIGH
}
else {                          //Dreiecksignal größer als Sinussignal
bitClear(PORTD, 7);             //Pin 6 LOW
}

//Sinusarray hochrechnen
m=m+1;
if(m>1599)
m=0;

//Dreieckarray hochrechnen
n=n+1;
if(n>15)
//if(n>7) //10kHz
n=0;
}

The Sin function idea sounds good too. How do I do that?

Hi, @thedice

Why do you need 8000 points in your sinewave?
What is your application that needs 25kHz.

How close to a real sinewave do you need your waveform?

Tom... :smiley: :+1: :coffee: :australia:

I compare a sine wave and a triangle wave to create a sinusoidal PWM.

Hi,
What model Arduino are you using?
So all you want is a PWM signal with sinusoidal varying duty cycle?

Tom... :smiley: :+1: :coffee: :australia:

to generate sine wave analogue signals I find it is simpler to use a DDS device such as the AD9850 (DDS Synthesizer)

I use a micro 32u4

Yes :sweat_smile:

Hi,
Make an array of 1/4 sinewave PWM values, then PWM it out with analogWrite.

analogWrite on most AVR controllers with Arduino are actually PWM outputs.
0 to 255 == 0 to 100% duty cycle.

Do you have a scope to measure the purity of your output?

Tom... :smiley: :+1: :coffee: :australia:

I have a scope on Monday to measure it.

to get an accurate measure of sine wave purity a spectrum analyzer is required

1 Like