You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Arduino Uno存储空间耗尽,添加音乐代码受阻:换Mega还是优化代码?

Arduino Uno Storage Full: Optimize Code or Upgrade to Mega?

Hey there! Let's break down your options clearly—both optimizing your existing code and upgrading to an Arduino Mega are viable solutions, but the best choice depends on your priorities (time vs. continued use of the Uno).

First: Let's Look at Code Optimization Opportunities

Your current issue is flash storage exhaustion from large melody arrays (like the melody and noteDurations in USSR_Theme()). Here are actionable fixes to free up space without hardware changes:

1. Store Melody Data in PROGMEM

By default, large global arrays are loaded into both flash and RAM, wasting space. Using PROGMEM keeps them only in flash (where your program lives) and avoids unnecessary RAM usage. Pair this with smaller data types to shrink the arrays by half:

Example Optimized USSR Theme:

// Define your note frequencies once (store in PROGMEM)
const uint16_t noteFreqs[] PROGMEM = {
  NOTE_G4, NOTE_D6, NOTE_C5, NOTE_A4, NOTE_B4, NOTE_E4,
  NOTE_F4, NOTE_C4, NOTE_D5, NOTE_E5, NOTE_F5
};

// Melody stored as indices to noteFreqs (1 byte each instead of 2)
const uint8_t ussrMelody[] PROGMEM = {
  0, 2, 0, 3, 4, 5, 5, 3, 0, 6, 0, 7, 7, 8, 8, 5, 6, 6,
  0, 3, 4, 2, 8, 9, 8, 2, 8, 4, 0, 2, 4, 3, 4, 5, 5, 3,
  0, 6, 0, 7, 7, 2, 4, 3, 0, 4, 2, 8, 9, 8, 2, 4, 2, 8,
  0, 0, 4, 2, 8, 2, 4, 3, 0, 3, 4, 5, 5, 0, 3, 4, 2, 3,
  4, 2, 3, 4, 2, 2, 10, 10, 9, 8, 2, 8, 9, 2, 2, 8, 2,
  4, 3, 4, 2, 3, 3, 2, 4, 3, 0, 7, 0, 3, 4, 2
};

// Durations stored as uint8_t (1 byte instead of 2)
const uint8_t ussrDurations[] PROGMEM = {
  8,4,6,16,4,8,8,4,6,16,4,8,8,4,8,8,4,8,8,4,8,8,2,4,
  6,16,4,8,8,4,6,16,4,8,8,4,6,16,4,6,16,4,6,16,8,8,8,
  8,2,8,8,8,8,3,8,8,8,8,8,2,8,8,8,8,3,8,8,8,8,8,4,6,
  16,4,6,16,4,8,8,2,2,8,8,8,8,3,8,2,2,8,8,8,8,3,8,2,
  4,6,16,4,4,2,4,4,1
};

// Generic function to play melodies from PROGMEM
void playProgMemMelody(const uint8_t* melody, const uint8_t* durations, int length) {
  for (int i = 0; i < length; i++) {
    // Read data from PROGMEM
    uint16_t freq = pgm_read_word(&noteFreqs[pgm_read_byte(&melody[i])]);
    uint8_t dur = pgm_read_byte(&durations[i]);
    
    int noteDuration = 2000 / dur;
    tone(A0, freq, noteDuration);
    delay(noteDuration * 1.3);
    noTone(A0);
  }
}

// Updated USSR_Theme function
void USSR_Theme(){
  playProgMemMelody(ussrMelody, ussrDurations, sizeof(ussrMelody));
}

This cuts the melody array size in half and keeps all data in flash, freeing up critical space for more tracks.

2. Remove Unused Code & Optimize Variables

  • Delete commented-out sections (like the lcd.print("Hey You") block)
  • Remove unused variables (e.g., button2 is read but never used)
  • Shrink variable types: recorded_button only holds 0/1/2, so use uint8_t instead of int; recorded_time can use uint16_t instead of int to save RAM (which reduces flash overhead indirectly)

3. Reuse Playback Logic

Instead of writing separate functions for each track, use the generic playProgMemMelody function for all your songs—this eliminates duplicate code and saves additional flash space.

Second: Upgrade to Arduino Mega

If you don't want to spend time optimizing code, upgrading to an Arduino Mega is a straightforward fix:

  • It has 256KB of flash storage (8x more than the Uno's 32KB), so you can add dozens more tracks without worrying about space
  • It also has 8KB of RAM (4x more than Uno), which gives you room to expand your recording feature (e.g., longer recordings)
  • All your existing code will work with minimal changes (your current pin setup is compatible)

Final Recommendation

  • Choose code optimization if you want to keep using your Uno, learn more about efficient Arduino programming, and only need a few extra tracks
  • Choose Arduino Mega if you plan to add many more tracks, want to avoid code tweaks, or might expand the project with more features later

Your Original Code for Reference

#include "pitches.h"
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3 ,2);
int notes[] = { NOTE_G4, NOTE_D6};
int button_music = 0;
int button2 =0;
int randNumber;
int key1 = 0;
int key2 = 0;
int recorded_button[200];
int recorded_time[200];
int pev_button;
char button = 0;
char button_index = 0;
int note_time;
unsigned long start_time;
char time_index;
void setup() {
  Serial.begin(9600);
  lcd.begin(16,2);
  pinMode(A5, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8, INPUT);
  pinMode(9,INPUT);
  // put your setup code here
}
void loop() {
  button_music = digitalRead(A4);
  button2 = digitalRead(A5);
  key1 = digitalRead(7);
  key2 = digitalRead(6);
  lcd.setCursor(0,0);
  lcd.print("Press button to");
  lcd.setCursor(0,1);
  lcd.print("play random song");
  if(button_music == HIGH) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("In Progress...");
    delay(5000);
    randNumber = random(1,4);
    Serial.println(randNumber);
    if(randNumber == 1) {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Tetris Theme...");
      delay(1000);
    } else if(randNumber == 2) {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("USSR Theme...");
      USSR_Theme();
      delay(1000);
    } else if(randNumber == 3) {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Pirates of the");
      lcd.setCursor(0,1);
      lcd.print("Caribbean...");
      delay(1000);
    }
  } else if(key1 == HIGH){
    // lcd.clear();
    // lcd.setCursor(0,0);
    // lcd.print("Hey You");
    // delay(2000);
    tone(A0,NOTE_G4,20);
  } else if (key2 == HIGH) {
    tone(A0,NOTE_D6,20);
  }
  // 3rd funtion (record)
  else if(digitalRead(9) == 1) {
    lcd.clear();
    delay(20);
    while(digitalRead(8) == 0) {
      lcd.setCursor(0, 0);
      lcd.print("Recording..");
      lcd.setCursor(0, 1);
      Detect_button();
      Play_tone();
    }
    ////////////////////////////////
    while (digitalRead(8) == 1) //If the toggle switch is set in Playing mode
    {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Now Playing..");
      for (int i = 0; i < sizeof(recorded_button) / 2; i++) {
        delay((recorded_time[i]) * 10); //Wait for before paying next tune
        if (recorded_button[i] == 0)
          noTone(A0); //user dint touch any button
        else
          tone(A0, notes[(recorded_button[i] - 1)]); //play the sound corresponding to the button touched by the user
      }
    }
    ////////////////////////////
    //
  }
}
void Detect_button(){
  key1 = digitalRead(7);
  key2 = digitalRead(6);
  pev_button = button;
  if(key1 != HIGH && key2 != HIGH) {
    button = 0;
  }
  if (key1 == HIGH){
    button = 1;
  }
  if (key2 == HIGH){
    button = 2;
  }
  /***record the pressed buttons in a array**/
  if (button != pev_button && pev_button != 0) {
    recorded_button[button_index] = pev_button;
    button_index++;
    recorded_button[button_index] = 0;
    button_index++;
  }
  //**end of recording**//
}
void Play_tone(){
  //**record time delay between notes**//
  if (button != pev_button) {
    lcd.clear();
    note_time = (millis() - start_time) / 10;
    recorded_time[time_index] = note_time;
    time_index++;
    start_time = millis();
  }
  //**end of recording **//
  if (button == 0) {
    noTone(A0);
    lcd.print("Pause");
  }
  if (button == 1) {
    tone(A0,NOTE_G4,20);
    lcd.print("NOTE G4");
  }
  if (button == 2) {
    tone(A0, NOTE_D6, 20);
    lcd.print("NOTE D6");
  }
}
void USSR_Theme(){
  int buzzerPin = 7;
  int melody[] = { NOTE_G4, NOTE_C5, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_E4, NOTE_E4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_G4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_B4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_E4, NOTE_E4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_G4, NOTE_C4, NOTE_C4, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_G4, NOTE_G4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_E4, NOTE_E4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_A4, NOTE_C5, NOTE_F5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_C4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5 };
  int noteDurations[] = { 8, 4, 6, 16, 4, 8, 8, 4, 6, 16, 4, 8, 8, 4, 8, 8, 4, 8, 8, 4, 8, 8, 2, 4, 6, 16, 4, 8, 8, 4, 6, 16, 4, 8, 8, 4, 6, 16, 4, 6, 16, 4, 6, 16, 8, 8, 8, 8, 2, 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 2, 8, 8, 8, 8, 3, 8, 8, 8, 8, 8, 4, 6, 16, 4, 6, 16, 4, 8, 8, 2, 2, 8, 8, 8, 8, 3, 8, 2, 2, 8, 8, 8, 8, 3, 8, 2, 4, 6, 16, 4, 4, 2, 4, 4, 1 };
  for (int thisNote = 0; thisNote < sizeof(melody) / 2; thisNote++) {
    int noteDuration = 2000 / noteDurations[thisNote];
    tone(A0, melody[thisNote], noteDuration);
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(buzzerPin);
  }
}

内容的提问来源于stack exchange,提问作者JOSE LUIS PASAYE

火山引擎 最新活动