Witam,
z tego co wiem to Arduino nie może wygenerować fali sinusoidalnej. Musisz użyć przybliżenia
Tu masz przykład czysto teoretyczny : https://www.tek.com/blog/tutorial-digital-analog-conversion-r-2r-dac
Przykładowy kod znaleziony w necie
// PIN 13 will have a 2.5 Hz square wave on it.
// PIN 3 will have a PWM signal on it, with a duty cycle that keeps changing in time. The mathematical 'time-average' of the PWM signal's amplitude will be proportional to the instantaneous amplitude of a DC-offsetted sinewave.
// NOTE that the frequency in this example is very low. The interrupt frequency is only 10 Hz, which means an interrupt every 0.1 second. If we have 256 values for our DC-offsetted sinewave (from the wave-table), then each 'amplitude' voltage will be generated with 1 second gaps, which means it would take a long time (such as 25.5 seconds) for a full cycle of the amplitude values.
//
boolean toggle1 = 0;
int pwmPin_timer1 = 3;
volatile int indexer = 0;
unsigned char sinewave[] = // Preset 256 values of a binary conversions of a sine wave having a POSITIVE DC OFFSET. It represents sinewave with a positive DC offet. This is done because the arduino doesn't handle NEGATIVE voltages.
{
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x06,0x07,0x09,
0x0a,0x0b,0x0c,0x0e,0x0f,0x11,0x12,0x14,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
0x25,0x28,0x2a,0x2c,0x2f,0x31,0x34,0x36,0x39,0x3c,0x3e,0x41,0x44,0x46,0x49,0x4c,
0x4f,0x52,0x55,0x58,0x5b,0x5e,0x61,0x64,0x67,0x6a,0x6d,0x70,0x73,0x77,0x7a,0x7d,
0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc4,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,
0xdb,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,0xee,0xef,0xf1,0xf2,0xf4,0xf5,
0xf6,0xf7,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfb,0xfa,0xfa,0xf9,0xf7,
0xf6,0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xdf,0xdd,
0xdb,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc4,0xc2,0xbf,0xbc,0xba,0xb7,0xb4,
0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,
0x80,0x7d,0x7a,0x77,0x73,0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,0x5b,0x58,0x55,0x52,
0x4f,0x4c,0x49,0x46,0x44,0x41,0x3e,0x3c,0x39,0x36,0x34,0x31,0x2f,0x2c,0x2a,0x28,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x16,0x14,0x12,0x11,0x0f,0x0e,0x0c,0x0b,
0x0a,0x09,0x07,0x06,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup(){
Serial.begin(9600);
pinMode(pwmPin_timer1, OUTPUT); //configured a valid pin for PWM output
cli();//stop interrupts
//NOTE: registers TCCR1A, TCCR1B, TCNT1, OCR1A etc. are PREDEFINED within a header file. They are registers related the setup of the arduino timers.
TCCR1A = 0;// initialise to zero.
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialise counter value to 0
OCR1A = 1563; // timer compare value; = [(16*10^6) / (10*1024)] - 1 (must be <65536) = MAXCOUNT = [(raw timer clock frequency) / (desired_interrupt_freq * prescale_divisor)] - 1, which comes from formula: prescaled_clockperiod = 1/prescaled_clockfreq; desired_interrupt_period = 1/10 = n.prescaled_clockperiod; maxcount = N = OCR0A = n-1; n is new divisor; prescaled_clockperiod = 1/(16MHz/prescale_divisor); a prescale_divisor of 1024 is set by CS10, CS11, CS12 of TCCR1B register.
TCCR1A |= 0;
// set up timer with prescaler = 1 and turn on CTC mode; CS10 CS11 and CS12 are bit0, bit1, and bit2 of the TCC1B register, respectively. Example prescaler options: Making CS11=1 and CS10=1 yields divide by 64. Making CS12=1 and CS11=1 yields divide by 1024. Refer to timer1 prescale table in a user manual for other combinations.
//TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10); //use this for divide by 64 (ie. 'prescaler 64')
TCCR1B |= (1 << WGM12)|(1 << CS12)|(1 << CS10); //use this for divide by 1024
//TCCR1B |= (1 << WGM12)|(1 << CS11); //use this for divide by 8
//TCCR1B |= (1 << WGM12)|(1 << CS10); //use this for divide by 1
// turn on CTC mode
//TCCR1B |= (1 << WGM12); //WGM12 is bit3 of the TCCR1B register (4th bit from the right). This turns on CTC mode (timer mode 4)
//Timer1 has 2 separate control registers. Each one contains bits for setting up features associated with timer1. Some bits, like the set of Waveform Generation WG bits are scattered so that some of the bits are in one register, while the other bits are in the second register.
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
//put things here if needed
}
ISR(TIMER1_COMPA_vect){//timer1 interrupt with frequency of 10Hz will toggle pin 13 (LED)
//this service routine generates pulse wave of frequency 10Hz/2 = 2.5Hz (takes two cycles for full wave- toggle high then toggle low) at digital pin 13
//analogWrite(pwmPin_timer1,128); //setPwmDuty(pwmPin_timer1, dutycycle)
//also generates PWM encoded DC-offsetted sinewave at digital pin 3
//write some code here .....
// pin 3, sinewave (plus positive DC offset) instantaneous amplitude encoded as PWM signals. The mathematical time-average of the constantly changing PWM signal will be the instantaneous amplitude of the encoded sine-wave. Therefore, it will be necessary to low-pass filter the PWM signal in order to 'observe' the encoded sine-wave.
analogWrite(pwmPin_timer1, sinewave[indexer]);
indexer++;
if (indexer == 256) {
indexer = 0;
}
// pin 13, square-wave signal; note that the frequency of the squarewave will be half of the interrupt frequency, due to the toggling. So if the interrupt frequency is 10 Hz, then the square wave's frequency will be 2.5 Hertz.
if (toggle1){
digitalWrite(13,HIGH);
toggle1 = 0;
}
else{
digitalWrite(13,LOW);
toggle1 = 1;
}
}
Za (https://forum.arduino.cc/index.php?topic=446209.4). W tym temacie jest poruszany przez Ciebie problem.