Voor een surprise projectje ben ik bezig om via een buzzer een theme song van Minecraft af te spelen.
Ik heb de sketch van een voorbeeld project. Dit werkt verder prima. Ik heb de code aangepast zodat het afspelen van het deuntje in de main loop zit en ik deze kan aanzetten met een druk op de knop. Veel spannender moet het niet worden. Echter wil ik nog 1 uitgang hoog maken wanneer het programma in de for loop zit van het afspelen van de theme song. Hiermee wil ik nog een ledstripje aansturen. Ik dacht dit simpel te doen door een digital.write toe te voegen, en dan deze pin hoog te maken. En deze weer laag te maken als die uit de for loop is.
Maar wanneer ik dit doe, dan klopt het "deuntje" niet meer. Hij lijkt dat niet meer de goede volgorde van de array te volgen. Echter zie ik niet terug waarom dit fout gaat. Op dit moment heb ik de extra stukjes code voor de aansturing van Pin3 als comment neergezet. Dan gaat het goed. Maar als ik zelfs al alleen in de void setup deze regel neerzet pinMode(3, OUTPUT); // sets the digital pin 3 as output, dan gaat het al fout.
Iemand enig idee? Wellicht zie ik iets simpels over het hoofd, maar ik zie niet wat.


// NB: ALL NOTES DEFINED WITH STANDARD ENGLISH NAMES, EXCEPT FROM "A" 
//THAT IS CALLED WITH THE ITALIAN NAME "LA" BECAUSE A0,A1...ARE THE ANALOG PINS ON ARDUINO.
// (Ab IS CALLED Ab AND NOT LAb)
#define	C0  16.35
#define	Db0	17.32
#define	D0	18.35
#define	Eb0	19.45
#define	E0	20.60
#define	F0	21.83
#define	Gb0	23.12
#define	G0	24.50
#define	Ab0	25.96
#define	LA0	27.50
#define	Bb0	29.14
#define	B0	30.87
#define	C1	32.70
#define	Db1	34.65
#define	D1	36.71
#define	Eb1	38.89
#define	E1	41.20
#define	F1	43.65
#define	Gb1	46.25
#define	G1	49.00
#define	Ab1	51.91
#define	LA1	55.00
#define	Bb1	58.27
#define	B1	61.74
#define	C2	65.41
#define	Db2	69.30
#define	D2	73.42
#define	Eb2	77.78
#define	E2	82.41
#define	F2	87.31
#define	Gb2	92.50
#define	G2	98.00
#define	Ab2	103.83
#define	LA2	110.00
#define	Bb2	116.54
#define	B2	123.47
#define	C3	130.81
#define	Db3	138.59
#define	D3	146.83
#define	Eb3	155.56
#define	E3	164.81
#define	F3	174.61
#define	Gb3	185.00
#define	G3	196.00
#define	Ab3	207.65
#define	LA3	220.00
#define	Bb3	233.08
#define	B3	246.94
#define	C4	261.63
#define	Db4	277.18
#define	D4	293.66
#define	Eb4	311.13
#define	E4	329.63
#define	F4	349.23
#define	Gb4	369.99
#define	G4	392.00
#define	Ab4	415.30
#define	LA4	440.00
#define	Bb4	466.16
#define	B4	493.88
#define	C5	523.25
#define	Db5	554.37
#define	D5	587.33
#define	Eb5	622.25
#define	E5	659.26
#define	F5	698.46
#define	Gb5	739.99
#define	G5	783.99
#define	Ab5	830.61
#define	LA5	880.00
#define	Bb5	932.33
#define	B5	987.77
#define	C6	1046.50
#define	Db6	1108.73
#define	D6	1174.66
#define	Eb6	1244.51
#define	E6	1318.51
#define	F6	1396.91
#define	Gb6	1479.98
#define	G6	1567.98
#define	Ab6	1661.22
#define	LA6	1760.00
#define	Bb6	1864.66
#define	B6	1975.53
#define	C7	2093.00
#define	Db7	2217.46
#define	D7	2349.32
#define	Eb7	2489.02
#define	E7	2637.02
#define	F7	2793.83
#define	Gb7	2959.96
#define	G7	3135.96
#define	Ab7	3322.44
#define	LA7	3520.01
#define	Bb7	3729.31
#define	B7	3951.07
#define	C8	4186.01
#define	Db8	4434.92
#define	D8	4698.64
#define	Eb8	4978.03

const int buttonPin = 2;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status

int melody[] = {C3, G3, C4, D4, E4, G3, C3, G3, C4, D4, E4, G3, LA2, G3, C4, D4, E4, G3, LA2, G3, C4, D4, E4, G3, F2, G3, C4, D4, E4, G3, F2, G3, C4, D4, E4, G3, G2, G3, C4, D4, E4, G3, G2, G3, C4, D4, E4, G3};

void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  // initialize the pin3 as an output:
  // pinMode(3, OUTPUT);       // sets the digital pin 3 as output
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
   for (int thisNote = 0; thisNote < 48; thisNote++) {
      //digitalWrite(3, HIGH);   // turn the LED on (HIGH is the voltage level)
      int noteDuration = 1000/4;
      tone(8, melody[thisNote],noteDuration);
      delay(noteDuration);
      }
      //digitalWrite(3, LOW);   // turn the LED off (LOW is the voltage level)
   }
   
}

Op een Arduino Leonardo onder 2.2.1 kan ik het probleem niet reproduceren, de code lijkt normaal te werken.

Ik heb een filmpje toegevoegd wat het probleem weergeeft.
Als eerste heb ik de code zonder declareren van de output pin. Dan gaat het goed.
Vervolgens declareer ik enkel pin 3 in de void setup. Dan gaat het al fout.
En als laatste haal ik de commentaar lijntje weg in de for loop. Dan zie je dat de uitgang wel hoog gemaakt wordt in de for loop, maar de themesong is nog steeds onjuist.

https://youtu.be/uif1mA8GvYA?si=E-YfM_jOW-cuWFMV

Pin3 en 11 zijn PWM pinnen. Als je de mogelijkheid hebt, gebruik dan een andere pin voor je led.
Zie hier:
https://www.arduino.cc/reference/en/language/functions/advanced-io/ton…

De melodie is hetzelfde, alleen de frequentie lijkt verschoven te zijn.
Mogelijk heeft u een bug of ongedocumenteerd feature gevonden, maar de snelste oplossing lijkt me een andere pin voor audio of lamp te proberen.

Een andere mogelijkheid is niet de Arduino pinMode en digitalWrite functies te gebruiken voor het aansturen van de pin, maar de register bits met de hand te zetten. Dat is goed te doen.

Op 14 december 2023 13:11:23 schreef Zonnepaneeltje:
Pin3 en 11 zijn PWM pinnen. Als je de mogelijkheid hebt, gebruik dan een andere pin voor je led.
Zie hier:
https://www.arduino.cc/reference/en/language/functions/advanced-io/ton…

Gewijzigd naar pin 4, maar helaas blijft het hetzelfde..

Edit: Gewijzigd naar pin 7, nu lijkt het 3x goed te gaan. Daarna gaat het weer fout.. :? Schiet mij maar lek!

[Bericht gewijzigd door Ricotjuh op (13%)]

IK verwacht een beetje dat het in de pinmode routine zit, die zet misschien ergens een register dat dit als effect heeft. Dan zou je het inderdaad kunnen vermijden door zelf naar de registers te schrijven. Probeer dat eens.

[Bericht gewijzigd door maartenbakker op (17%)]

int noteDuration = 1000/4;

Wijzigt niet gedurende de ganse for loop. Zet die gewoon buiten je loop. Of zelfs gewoon als een constante declareren.

Je kan de led uitgang ook hoog maken net voor het starten van de loop en uitzetten na het einde. Een uitgang die niet tot dezelfde 8 uitgangen behoort als de melody uitgang zou moeten lukken.

Heb er nu dit van gemaakt en lijkt het wel te werken.
Alleen is dit dan een "soort van bug" in de software tijdens het gebruik van pinMode en de Tone() commando?
Want in al mijn andere arduino programma's maak ik normaliter gebruik van pinMode


void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  // initialize the pin3 as an output:
  //pinMode(7, OUTPUT);       // sets the digital pin 3 as output
  DDRD = DDRD | B10000000;
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
   for (int thisNote = 0; thisNote < 48; thisNote++) {
      digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
      tone(8, melody[thisNote],noteDuration);
      delay(noteDuration);
      }
      digitalWrite(7, LOW);   // turn the LED off (LOW is the voltage level)
    }
}

[Bericht gewijzigd door Ricotjuh op (13%)]

Je zet nu 48 keer de LED aan en weer uit. Kun je dat niet beter buiten de for loop doen, heeft zelfde effect en lost misschien het probleem op (geen extra CPU cycles binnen de for loop door digitalWrite() )

/edit, P3 dus niet gebruiken... (thnx, fcapri). Aan/uit zetten buiten de loop wel doen (LED_BUILTIN = de LED op het arduino bordje).


pinMode(LED_BUILTIN, OUTPUT)

if (buttonState == HIGH) {

   digitalWrite(LED_BUILTIN, HIGH);

   for (int thisNote = 0; thisNote < 48; thisNote++) {
      int noteDuration = 1000/4;
      tone(8, melody[thisNote],noteDuration);
      delay(noteDuration);
   }

   digitalWrite(LED_BUILTIN, LOW); 
}

je moet eens goed de tone() nalezen. als je die gebruikt, zijn er een aantal pwm uitgangen die je NIET meer mag gebruiken.
3 is er eentje van ;-)

Use of the tone() function will interfere with PWM output on pins 3 and 11 (on boards other than the Mega).

https://www.arduino.cc/reference/en/language/functions/advanced-io/ton…

blijf gewoon weg van alle PWM pinnen, misbruik eventueel een analoge pin om uw leds te laten branden.

Je zet nu 48 keer de LED aan en weer uit. Kun je dat niet beter buiten de for loop doen

Maar dat doet hij ook. Alleen staan de haakjes op een rare plaats dus je ziet het niet. Dat is precies de reden dat ik die stijl niet gebruik :) .

Op 14 december 2023 16:16:58 schreef Schimanski:
Je zet nu 48 keer de LED aan en weer uit. Kun je dat niet beter buiten de for loop doen, heeft zelfde effect en lost misschien het probleem op (geen extra CPU cycles binnen de for loop door digitalWrite() )

/edit, P3 dus niet gebruiken... (thnx, fcapri). Aan/uit zetten buiten de loop wel doen (LED_BUILTIN = de LED op het arduino bordje).


pinMode(LED_BUILTIN, OUTPUT)

if (buttonState == HIGH) {

   digitalWrite(LED_BUILTIN, HIGH);

   for (int thisNote = 0; thisNote < 48; thisNote++) {
      int noteDuration = 1000/4;
      tone(8, melody[thisNote],noteDuration);
      delay(noteDuration);
   }

   digitalWrite(LED_BUILTIN, LOW); 
}

Voor de werking maakt dat niets uit volgens mij. Ik heb net getest om de digitalWrite voor het for command te zetten, maar dit lijkt niets te verschillen. Voor de zekerheid ook op pin7 gemeten met de scoop, maar ik zie daar geen pulsen voorbij komen. Enkel een puls na het indrukken van de start button.
Daarnaast even getest met de builtin led, maar dan gaat ie weer de fout in zoals in de video is aangegeven.
Dus op dit moment lijkt het enkel "goed" te werken als ik de uitgang zo: DDRD = DDRD | B10000000; definieer

Op 14 december 2023 16:22:00 schreef fcapri:
je moet eens goed de tone() nalezen. als je die gebruikt, zijn er een aantal pwm uitgangen die je NIET meer mag gebruiken.
3 is er eentje van ;-)

Je kunt de hardware PWM functie van die pin niet meer gebruiken, zeer waarschijnlijk omdat ze dezelfde timer gebruiken om de interrupt te maken. Ik vind het stom dat ze vervolgens in die interrupt naar een pin gaan schrijven, ze hadden ook pin 3 kunnen togglen op de compare match.

Je kunt die pin dus prima gebruiken voor iets anders.

Op 14 december 2023 17:12:37 schreef deKees:
[...]

Maar dat doet hij ook. Alleen staan de haakjes op een rare plaats dus je ziet het niet. Dat is precies de reden dat ik die stijl niet gebruik :) .

Ik zie het nu, hij zet elke itteratie de LED opnieuw aan, en na afloop van de for-loop weer uit.

Moet de input pin geen pullup of pulldown hebben? Of heb je die extern?

Extern heb ik een pulldown weerstand zitten.