2016-08-11 9 views
0

Ich verwende eine eigenständige Atmega328P mit zwei Piezo-Elementen, um etwas Musik zu erzeugen. Ich habe einige Konstanten mit den Frequenzen der Noten definiert. Dann habe ich eine Struktur definiert, die die Note für den ersten und zweiten Piezo und die Länge der Note enthält. Dann habe ich mehr Arrays dieser Strukturen erstellt, um jeden Song zu beschreiben. Das Problem ist, dass auf diese Weise ich nicht genügend Arbeitsspeicher haben. Ich habe versucht, die Arrays von Strukturen im PROGMEM zu speichern, um dieses Problem zu vermeiden. Ich habe versucht, eine kleine Bibliothek namens PROGMEM_readAnything, die Funktionen memcpy_P() oder pgm_read_word() und pgm_read_byte() zu verwenden, aber in allen Fällen bekomme ich das gleiche Problem.Arduino Array von Strukturen in PROGMEM

Während ich das Array von NOTES durchläuft, überspringt einige der Elemente, während liest und spielt die anderen korrekt. Es überspringt immer dieselben Elemente und nicht nur zufällige. Ich habe sogar versucht, den Mikrocontroller zu ändern und dachte, dass bestimmte Teile des Chips durch etwas beschädigt worden sein könnten, aber das Hochladen der gleichen Skizze habe ich die gleichen Ergebnisse, so dass der Mikrocontroller wahrscheinlich intakt ist. Hier

ist der Code:

#include <Tone.h> 
#include <avr/pgmspace.h> 

//Define the notes frq 
#define G2 98 
#define Gs2 104 
#define Ab2 104 
#define A2 110 
#define As2 116 

//... and so on with many other music notes ... 

#define Fs7 2960 
#define Gb7 2960 
#define G7 3136 

//Rest 
#define R 0 

typedef struct { 
    int n1; 
    int n2; 
    byte units; 
} NOTES; 

Tone buzzer1; 
Tone buzzer2; 

int myTempo = 100; 

//Walkyrie 
const NOTES walkyrie[] PROGMEM = { 

          {Fs3, Fs4, 2}, 
          {B3, B4,3}, 
          {Fs3, Fs4, 1}, 
          {B3, B4, 2}, 
          {D4, D5, 6}, 
          {B3, B4, 6}, 
          {D4, D5, 3}, 
          {B3, B4, 1}, 
          {D4, D5, 2}, 
          {Fs4, Fs5, 6}, 
          {D4, D5, 6}, 
          {Fs4, Fs5, 3}, 
          {D4, D5, 1}, 
          {Fs4, Fs5, 2}, 
          {A4, A5, 6}, 
          {A3, A4, 6}, 
          {D4, D5, 3}, 
          {A3, A4, 1}, 
          {D4, D5, 2}, 
          {Fs4, Fs5, 6}, 
          {R, 0, 4}, 
          {A3, A4, 2}, 
          {D4, D5, 3}, 
          {A3, A4, 1}, 
          {D4, D5, 2}, 
          {Fs4, Fs5, 6}, 
          {D4, D5, 6}, 
          {Fs4, Fs5, 3}, 
          {D4, D5, 1}, 
          {Fs4, Fs5, 2}, 
          {A4, A5, 6}, 
          {Fs4, Fs5, 6}, 
          {A4, A5, 3}, 
          {Fs4, Fs5, 1}, 
          {A4, A5, 2}, 
          {Cs5, Cs6, 6}, 
          {Cs4, Cs5, 6}, 
          {Fs4, Fs5, 3}, 
          {Cs4, Cs5, 1}, 
          {Fs4, Fs5, 2}, 
          {As4, As5, 6} 



         }; 

void playSong() 
{ 
    //We store the frq of the second pizo in this variable 
    int secondFrq = 0; 
    Serial.println(sizeof(walkyrie)/sizeof(walkyrie[0])); 
    //Walk through the array of music 
    for(int i = 0; i < sizeof(walkyrie)/sizeof(walkyrie[0]); i++) 
    { 

     int n1; 
     int n2; 
     byte units; 
     // Only play if it is not a rest 
     if(walkyrie[i].n1 > 0) 
     { 


      n1 = pgm_read_word(&(walkyrie[i].n1)); 
      n2 = pgm_read_word(&(walkyrie[i].n2)); 
      units = pgm_read_byte(&(walkyrie[i].units)); 

      Serial.print("Row "); 
      Serial.print(i); 
      Serial.print(": Frq1: "); 
      Serial.print(n1); 
      Serial.print(" Frq2: "); 
      Serial.print(n2); 
      Serial.print(" Units: "); 
      Serial.println(units); 

      //Play the note of the first piezo 
      buzzer1.play(n1, (units*myTempo)); 
      //If the frq of the second piezo is 0, we play the same note  as the first, else the note set for the second one 
      if(n2 == 0) 
      { 
       secondFrq = n1; 
      }else{ 
       secondFrq = n2; 
      } 

      buzzer2.play(secondFrq, (units*myTempo)); 

     } 

    //Then we wait for the note to end plus a little, between two notes 
    delay((units*myTempo) + 10); 

    } 
} 


void setup() { 
    Serial.begin(9600); 
    buzzer1.begin(11); 
    buzzer2.begin(12); 
} 

void loop() 
{ 
    playSong(); 
} 

ich einige Zeilen hinzugefügt in seriellen Monitor zu sehen, was passiert. liest sie die richtige Länge ... Der Ausgang des seriellen Monitors ist die folgende:

41             (correct length) 
Row 1: Frq1: 247 Frq2: 499 Units: 3  (row 0 - the first note is already missing) 
Row 2: Frq1: 185 Frq2: 370 Units: 1 
Row 3: Frq1: 247 Frq2: 499 Units: 2  (row 4 missing) 
Row 5: Frq1: 247 Frq2: 499 Units: 6  (row 6-7 missing) 
Row 8: Frq1: 294 Frq2: 587 Units: 2 
Row 9: Frq1: 370 Frq2: 740 Units: 6 
Row 10: Frq1: 294 Frq2: 587 Units: 6 
Row 11: Frq1: 370 Frq2: 740 Units: 3 
Row 12: Frq1: 294 Frq2: 587 Units: 1 
Row 13: Frq1: 370 Frq2: 740 Units: 2 
Row 14: Frq1: 440 Frq2: 880 Units: 6 
Row 15: Frq1: 220 Frq2: 440 Units: 6 (row 16-17 missing) 
Row 18: Frq1: 294 Frq2: 587 Units: 2 
Row 19: Frq1: 370 Frq2: 740 Units: 6 
Row 20: Frq1: 0 Frq2: 0 Units: 4 
Row 21: Frq1: 220 Frq2: 440 Units: 2 
Row 22: Frq1: 294 Frq2: 587 Units: 3 
Row 23: Frq1: 220 Frq2: 440 Units: 1 
Row 24: Frq1: 294 Frq2: 587 Units: 2 
Row 25: Frq1: 370 Frq2: 740 Units: 6 
Row 26: Frq1: 294 Frq2: 587 Units: 6 
Row 27: Frq1: 370 Frq2: 740 Units: 3 
Row 28: Frq1: 294 Frq2: 587 Units: 1 
Row 29: Frq1: 370 Frq2: 740 Units: 2 
Row 30: Frq1: 440 Frq2: 880 Units: 6 
Row 31: Frq1: 370 Frq2: 740 Units: 6 
Row 32: Frq1: 440 Frq2: 880 Units: 3 
Row 33: Frq1: 370 Frq2: 740 Units: 1 
Row 34: Frq1: 440 Frq2: 880 Units: 2 
Row 35: Frq1: 554 Frq2: 1109 Units: 6 
Row 36: Frq1: 277 Frq2: 554 Units: 6 
Row 37: Frq1: 370 Frq2: 740 Units: 3 
Row 38: Frq1: 277 Frq2: 554 Units: 1 
Row 39: Frq1: 370 Frq2: 740 Units: 2 
Row 40: Frq1: 466 Frq2: 932 Units: 6 

Hat jemand irgendwelche Ideen, warum es passiert? Oder hat jemand eine bessere und effizientere Lösung dieses Problems? Vielen Dank im Voraus für jede Hilfe.

+0

Es klingt wie Sie müssen lernen, wie Sie einen Debugger verwenden, um durch Ihren Code zu gehen.Mit einem guten Debugger können Sie Ihr Programm Zeile für Zeile ausführen und sehen, wo es von dem, was Sie erwarten, abweicht. Dies ist ein essentielles Werkzeug, wenn Sie programmieren wollen. Weiterführende Literatur: ** [Wie kleine Programme zu debuggen] (http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) ** – NathanOliver

Antwort

3

In dieser Zeile überprüfen Sie die Daten, aber Sie haben nicht getan ‚pgm_read_word()‘, um tatsächlich die Daten aus dem Flash-Speicher erhalten:

if(walkyrie[i].n1 > 0) 

Wenn durch Zufall Sie Erhalten Sie einen Wert ungleich Null, dann lesen Sie die Werte korrekt aus dem Flash, aber ansonsten überspringen Sie diese Zeile.

Ein weiterer Beweis:

Row 20: Frq1: 0 Frq2: 0 Units: 4 

Hier n1 Null ist, aber dieser Test sollte die Zeile übersprungen haben.

Auch die Logik für einen "Rest" ist ein wenig aus. Im Moment lesen Sie nicht die Einheiten für die Dauer des Rests, also verwendet es den vorherigen Wert (von einer gespielten Note).

Ich denke, ich würde alle drei Werte zuerst bekommen, und dann überprüfen Sie sie.

Ich würde auch die Frequenzen in ein Byte kodieren und eine Nachschlagetabelle verwenden, um die "Schlüsselnummer" in eine Frequenz umzuwandeln (wie MIDI-Schlüsselnummern). Ihr Array von Strukturen wird auf diese Weise ein wenig kleiner sein. Vielleicht schalten Sie auch das __packed__ (was auch immer) Attribut ein, um das Auffüllen zwischen den Einträgen zu vermeiden - wenn das Speichern von Flash-Speicherplatz wichtig ist (

)

Klingt lustig! Viel Glück!