Заменитель игрушечного музыкального телефона для дочери пятилетки

yhostsy
Offline
Зарегистрирован: 05.05.2019

Добрый день. Проблема такая: к нано подключил экран 5110, самодельный cd-шилд, динамик 8ом , 4 кнопки к 0 аналоговому входу, на карточке создал три папки с wav (1 - музыка пока 10, 2- сказки пока 3, 3- буквы (произношения) пока 33), и все это 21558 байт (70%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1749 байт (85%) динамической памяти.Недостаточно памяти, программа может работать нестабильно.
 

Как работает (задумывалось): дочь включает , появляется её фото ч/б 80 на 46 пикселей и звучит "привет Алиса" (01.wav в корне флешки). Далее кнопками 2вперед или 4назад меняет композицию, 1 и 3 меняют папку из которой брать, композиции сразу воспроизводятся по счетчику папок и счетчику вав и отображаются счетчики на экранчике. Когда счетчик папки 3 то открывается буква А на экранчике и её озвучка и кнопками дочка пролистывает буквы. Но вот беда: добавив кучу условий if для вывода руских букв перестает функционировать озвучка и фоспроизведение. Код корявый, не пинайте начинающего.

Прошу помочь с проблемой озвучки.

P.S пины подключения навесного описаны в коде

// кнопки так у меня
///  1 папки    4 стоп
///  2 назад    3 вперед


#include "SD.h"
#include "TMRpcm.h"
#include "Adafruit_GFX.h"
#include "Adafruit_PCD8544.h"
#include "SPI.h"
TMRpcm tmrpcm;
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
//#define SD_ChipSelectPin 10

//Определяем переменные, которые понадобятся нам для хранения измеряемого значения
int value, old_value, schetchik_wav, schetchik_papok;
byte key_number;
//Храним в памяти референсные значения
static int key_values[4]={100,500,620,720};
static int vsego_kompoziciy[3]={10,3,33};

const unsigned char PROGMEM alisaBmp[] = {
0xe4, 0xaa, 0xa5, 0x51, 0x7f, 0xea, 0x95, 0x57, 0x6f, 0xff, 
0xd2, 0x95, 0x52, 0xa5, 0xdf, 0xfd, 0x49, 0x55, 0xb5, 0x55, 
0xca, 0x49, 0x2a, 0x57, 0xff, 0xff, 0xa5, 0x56, 0xdb, 0xee, 
0xd2, 0xa4, 0x95, 0x5b, 0xff, 0xff, 0xd4, 0xab, 0x6e, 0xbb, 
0xca, 0x49, 0x49, 0x6f, 0xff, 0xff, 0x72, 0x2e, 0xab, 0xdd, 
0xd2, 0x92, 0x25, 0xff, 0xff, 0xff, 0xe9, 0x45, 0xdd, 0x6f, 
0xca, 0xa4, 0x95, 0x6f, 0xbf, 0xfd, 0xfa, 0x56, 0xb7, 0xb5, 
0xd5, 0x12, 0x55, 0xfd, 0xfb, 0xb7, 0xad, 0x22, 0xda, 0xff, 
0xaa, 0xc9, 0x2b, 0xb7, 0xdf, 0xdf, 0xf4, 0x95, 0x6f, 0x55, 
0xa4, 0x55, 0x4a, 0xde, 0xf5, 0xfd, 0x5e, 0x4b, 0xb5, 0xfe, 
0xab, 0x49, 0x2b, 0xeb, 0xb7, 0x4f, 0xea, 0xa4, 0xd6, 0xab, 
0x54, 0xa4, 0xab, 0x76, 0xd5, 0x54, 0x56, 0x13, 0x5b, 0x55, 
0xab, 0x56, 0xad, 0xaa, 0xab, 0x55, 0xab, 0x4a, 0xed, 0xbe, 
0x55, 0x52, 0xb7, 0xea, 0xa4, 0xaa, 0xb6, 0xad, 0x56, 0xd3, 
0xb5, 0x5a, 0xab, 0x55, 0x55, 0x15, 0x5a, 0xbf, 0xf5, 0x6d, 
0xad, 0x55, 0x5d, 0xea, 0x44, 0xa2, 0xaf, 0xfb, 0x7f, 0xb6, 
0xab, 0x6a, 0xaf, 0x6a, 0x92, 0x14, 0x55, 0xff, 0xef, 0xdd, 
0xb5, 0x55, 0x75, 0xea, 0x48, 0xa2, 0xbf, 0xff, 0xfe, 0xe5, 
0xd5, 0x55, 0x5f, 0xb5, 0x25, 0x15, 0x4b, 0x7f, 0xfe, 0xb6, 
0xab, 0x56, 0xab, 0xd4, 0xa8, 0xaa, 0xbf, 0xff, 0xf3, 0x5a, 
0xad, 0x55, 0x5e, 0xd5, 0x55, 0x17, 0x4b, 0x7f, 0xdd, 0xab, 
0xb5, 0x6a, 0xaf, 0xb2, 0xba, 0x4b, 0x6f, 0xff, 0xaa, 0xf5, 
0xaa, 0xa5, 0x71, 0xd4, 0xb1, 0x2a, 0x95, 0xbe, 0x6f, 0x5d, 
0xab, 0x5a, 0xac, 0x52, 0x4c, 0xa9, 0x57, 0xf5, 0xb5, 0x55, 
0xaa, 0xaa, 0xd3, 0x69, 0x22, 0x4a, 0x55, 0xba, 0xda, 0xea, 
0xaa, 0xaa, 0xb9, 0x54, 0x95, 0x29, 0x2a, 0xed, 0x6b, 0x56, 
0xaa, 0xd5, 0x6a, 0xaa, 0x48, 0x94, 0x97, 0xeb, 0xad, 0xab, 
0xd5, 0x55, 0xb8, 0xb1, 0x22, 0xa8, 0x56, 0xda, 0xb6, 0xb4, 
0xd5, 0x56, 0xd6, 0x54, 0x89, 0x22, 0x9b, 0xad, 0x55, 0x57, 
0xd5, 0x51, 0x5a, 0xb5, 0x24, 0x94, 0x4f, 0x75, 0xb5, 0x54, 
0xea, 0xad, 0x6d, 0x54, 0x89, 0x49, 0x25, 0xaa, 0xd5, 0x5b, 
0xaa, 0xa5, 0x5e, 0xaa, 0x44, 0x24, 0x5e, 0xb6, 0xaa, 0xd5, 
0xf5, 0x55, 0x77, 0xba, 0x92, 0x92, 0x8b, 0x5a, 0xab, 0x5a, 
0xfa, 0xaa, 0xbd, 0xf4, 0x2a, 0xda, 0x2d, 0xaa, 0xad, 0x6a, 
0xd2, 0xa5, 0x77, 0xfa, 0x85, 0x54, 0xaa, 0xd5, 0x55, 0x56, 
0xfa, 0xaa, 0xdf, 0xfa, 0x52, 0x52, 0x5f, 0x56, 0xaa, 0xb5, 
0xba, 0xab, 0x7d, 0xba, 0x89, 0x09, 0x2a, 0xa9, 0x6d, 0xd5, 
0xfa, 0xaa, 0xef, 0xfd, 0x24, 0xa4, 0xbf, 0xd6, 0xaa, 0x55, 
0xda, 0xad, 0xbe, 0xfa, 0xaa, 0x52, 0xfa, 0xaa, 0xb5, 0xaa, 
0xfd, 0x56, 0xfb, 0xdd, 0x51, 0x0b, 0xff, 0xd5, 0x56, 0xb6, 
0xdc, 0xab, 0xef, 0x7c, 0xaa, 0xaa, 0xee, 0xaa, 0xd5, 0x4b, 
0xf7, 0x55, 0xbf, 0xfd, 0x14, 0xaa, 0xfb, 0xd5, 0x56, 0xda, 
0xbf, 0x5b, 0xfb, 0x6c, 0xa5, 0x52, 0xff, 0x6d, 0x5b, 0x55, 
0xfb, 0xae, 0xdd, 0xfa, 0x92, 0x25, 0xef, 0xb3, 0x6a, 0xaa, 
0xdf, 0xc7, 0x6b, 0x55, 0x24, 0x92, 0xfb, 0xdd, 0xad, 0xdb, 
0xf6, 0xf3, 0xbd, 0x54, 0x92, 0x49, 0x5e, 0xaa, 0xb6, 0x6d, 
0xbf, 0x1d, 0xc0, 0x55, 0x49, 0x25, 0x6b, 0xf5, 0x55, 0xaa, 
0xec, 0xeb, 0x25, 0x2a, 0x24, 0x95, 0x53, 0x5e, 0xd6, 0xb7
};

void setup(){

  tmrpcm.speakerPin = 9; 
  tmrpcm.volume(6);
  if (!SD.begin(10)) { 
    tone(9,200);
    delay(200);
    noTone(9); 
    return;   
  }
  tmrpcm.play("02.wav"); 
  schetchik_papok = schetchik_wav = 1;
 display.begin();
 display.cp437(true);
 display.clearDisplay();
 display.display();
 // установка контраста
 display.setContrast(48);
 
 // отрисовка изображения
 display.drawBitmap(0, 0, alisaBmp, 80, 48, BLACK); 
 display.display();
 delay(1000);
}

void loop() {
  value = analogRead(0);
  //если значение отличается от предыдущего больше, чем на 50, и оно меньше 1000
  if (abs(value-old_value) > 50 && value < 1010)
  { 
      key_number = get_key(value);
      switch (key_number) 
      {
        case 1:
          schetchik_papok = schetchik_papok + 1;
          schetchik_wav = 1;
          if (schetchik_papok > 3) {schetchik_papok = 1;} //тут указываем количество папок 3
          playmusic();
          //delay(700);
          break;
        case 2:
          schetchik_wav = schetchik_wav - 1;
          if (schetchik_wav <= 0) {schetchik_wav = vsego_kompoziciy[schetchik_papok-1];}
          playmusic(); 
          //delay(700);
          break;
        case 3:
          schetchik_wav = schetchik_wav + 1;
          if (schetchik_wav > vsego_kompoziciy[schetchik_papok-1]) {schetchik_wav = 1;}
          playmusic();
          //delay(700);
          break;
        case 4:
          schetchik_papok = schetchik_papok - 1;
          schetchik_wav = 1;
          if (schetchik_papok <= 0) {schetchik_papok = 3;} //тут указываем количество папок
          playmusic();
          //delay(700);
          break;
         default: old_value = value; delay(700);
      }
  }
  old_value = value;
  delay(200);
}

void playmusic() 
    {
     display.clearDisplay();
     display.display();
     String nazvanie;
     nazvanie = schetchik_papok;
     nazvanie = nazvanie +'/'+ schetchik_wav+".wav";
     char nazvanie_array[nazvanie.length()];
     nazvanie.toCharArray(nazvanie_array, nazvanie.length()+1);
     tmrpcm.play(nazvanie_array);
     delay(50);
           if (schetchik_papok == 3) 
              {
               display.setCursor(30,0);
               display.setTextSize(5);
               if (schetchik_wav == 1){display.print(utf8rus("А")); }
               if (schetchik_wav == 2){display.print(utf8rus("Б")); }
               if (schetchik_wav == 3){display.print(utf8rus("В")); }
               if (schetchik_wav == 4){display.print(utf8rus("Г")); }
               if (schetchik_wav == 5){display.print(utf8rus("Д")); }
               if (schetchik_wav == 6){display.print(utf8rus("Е")); }
               if (schetchik_wav == 7){display.print(utf8rus("Ё")); }
               if (schetchik_wav == 8){display.print(utf8rus("Ж")); }
               if (schetchik_wav == 9){display.print(utf8rus("З")); }
               if (schetchik_wav == 10){display.print(utf8rus("И")); }
               if (schetchik_wav == 11){display.print(utf8rus("Й")); }
               if (schetchik_wav == 12){display.print(utf8rus("К")); }
               if (schetchik_wav == 13){display.print(utf8rus("Л")); }
               if (schetchik_wav == 14){display.print(utf8rus("М")); }
               if (schetchik_wav == 15){display.print(utf8rus("Н")); }
               if (schetchik_wav == 16){display.print(utf8rus("О")); }
               if (schetchik_wav == 17){display.print(utf8rus("П")); }
               if (schetchik_wav == 18){display.print(utf8rus("Р")); }
               if (schetchik_wav == 19){display.print(utf8rus("С")); }
               if (schetchik_wav == 20){display.print(utf8rus("Т")); }
               if (schetchik_wav == 21){display.print(utf8rus("У")); }
               if (schetchik_wav == 22){display.print(utf8rus("Ф")); }
               if (schetchik_wav == 23){display.print(utf8rus("Х")); }
               if (schetchik_wav == 24){display.print(utf8rus("Ц")); }
               if (schetchik_wav == 25){display.print(utf8rus("Ч")); }
               if (schetchik_wav == 26){display.print(utf8rus("Ш")); }
               if (schetchik_wav == 27){display.print(utf8rus("Щ")); }
               if (schetchik_wav == 28){display.print(utf8rus("Ъ")); }
               if (schetchik_wav == 29){display.print(utf8rus("Ы")); }
               if (schetchik_wav == 30){display.print(utf8rus("Ь")); }
               if (schetchik_wav == 31){display.print(utf8rus("Э")); }
               if (schetchik_wav == 32){display.print(utf8rus("Ю")); }
               if (schetchik_wav == 33){display.print(utf8rus("Я")); }     
              }
             else {
              display.setCursor(0,0);
              display.setTextSize(3);
              display.println(schetchik_papok);
              display.print(schetchik_wav);
              }
      display.display();
      delay(700);
    }

//функция для определения номера нажатой кнопки
int get_key(int value){
  //Идем по массиву референсных значений
  for (int i=0; i<4; i++){
    //если измеренное значение попало в диапазон между референсными значениями, выводим номер диапазона
    if (value < key_values[i]) return i+1;
  }
}


String utf8rus(String source)
{
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Вы ошиблись разделом. Здесь публикуют отчёты о готовых проектах. Вопросы - это в другие разделы.

yhostsy
Offline
Зарегистрирован: 05.05.2019

прошу прощения. первый раз на этом форуме и с единственной просьбой. Если все настолько строго , админы перенесите в нужное место.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

А по сути, откажитесь от Adafruit'овских библиотек и работайте с экраном напрямую без буффера. Там очень простой интерфейс. Все необходимые буквы просто заготовьте как битмапы, причем следите за блочностью этого экрана и делайте битмапы с размерами кратными размеру блока. Тогда с памятью у Вас проблем не будет.

yhostsy
Offline
Зарегистрирован: 05.05.2019

Ого, для меня как для начинающего чегото сложновато понять даже то что вы написали. Если отказаться от адафулта то как пользоваться экраном? Пробовал делать битмапом буквы (но с вкл адафултом) размер букв был схожим, работало черезь пень колоду т.е. пару звуков воспроизводило и потом в любой момент начинало свистеть хрипеть и т.д и потом уходило в перезагрузку. Заметил просто что когда динамической памяти менее 80 работает более менее стабильно (убирал if с выводом русских букв). Когда делал битмапы букв, росла память устройства и динамической было 83 что тоже не айс. Думаю гдето надо просто подрезать  лишнего

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Ну, да, так и надо. Как раз адафрутовские библиотеки и есть лишнее. Они тянут off-scrren буфер, который сжирает всю память. А глюки и перезагрузка - как раз симтомы нехватки памяти.

Тут у Вас два варианта - почитать даташит на дисплей (там нет ничего заумного) и написать работу с ним вручную. Или можно попробовать взять какую-ниюудь безбуферную библиотеку и попытаться сделать всё на ней.

Вот, например, простенькая безбуферная библиотека. Только я бы выбросил из неё раодные шрифты, заменив их на "только то. что мне нужно". Для рисования шрифтов (и картинко) можно использовать кучу бесплатных утилит. Например, такую.

Но если Вам всё это тяжело, то поищите на форуме тему про безбуфреную русифицированную библиотеку от andriano. Он там вроде всё сделал и, если что, он подскажет что там да как.

А на то, что подрезав что-то (не трогая библиотеки) Вы решите проблему - даже не думайте. Откройте файл Adafruit_GFX.cpp и посмотрите. Там кроме всего еще и динамические malloc'и имеются.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

yhostsy, насколько я понимаю, Ваши задумки вошли в конфликт с весьма ограниченными ресурсами микроконтроллера. Здесь я вижу несколько вариантов поведения:

1. Заменить контроллер на более мощный. Минусы - габариты, если Мега, и требует квалификации, если stm32.

2. Оптимизировать код по ресурсам. Минусы - требует квалификации.

3. Урезать функциональность. Минусы - обидно.

4. Обратиться за помощью в раздел "Ищу исполнителя". Минусы - дорого.

5. Забыть об этом и заняться чем-то другим. Минусы - удар по самоуважению и, возможно, репутации.

step962
Offline
Зарегистрирован: 23.05.2011

Строки 154-186 замените на две:

// эту строку размещаем вверху - в области определения переменных/констант
const char Letter[] ="АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
// а этой заменяем строки 154-186
display.print(utf8rus(Letter[schetchik_wav-1]));

 

yhostsy
Offline
Зарегистрирован: 05.05.2019

sketch_may05a:156: error: converting to 'String' from initializer list would use explicit constructor 'String::String(char)'

                display.print(utf8rus(Letter[schetchik_wav-1]));

 

 

step962
Offline
Зарегистрирован: 23.05.2011

Судя по сообщению об ошибке, функция utf8rus не в состоянии переварить переменную типа char. Значит, нужно помочь ей, преобразовав char в String. Попробуйте такой вариант:

display.print(utf8rus(String(Letter[schetchik_wav-1])));