Переполняется SRAM командами для пульта, помогите разобраться.
- Войдите на сайт для отправки комментариев
Есть кондишн самсунг, IR коды для его управления я считал осциллографом, и они работают, каждый по отдельности, если в скетче только один код.
Но если я в скетче записываю хотя бы три кода, оперативка переполняется, программа ведёт себя непредсказуемо.
С помощью Progmem вроде как массивы кодов записываются во флэш память, но потом возникают трудности с чтением массива и посылкой его на передатчик с помощью команды IRdend.
Может быть можно как - то задать тип массива как константу, чтобы ардуина не пыталась её в оперативке размещать?
Рабочий код на включение кондиционера на 24 градуса, обогрев, такой:
#include <IRremote.h> IRsend irsend; void setup() { Serial.begin(9600); } void loop() { unsigned int preraw[2] = {600,7900}; unsigned int raw[347] = { 2900,9000,500,500,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,500,500,500,500,1500,500,500,500,500,500,1500,500,1500,500,1500,500,1500,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,1500,500,1500,500,1500,500,3000,3000, 9000,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,500,500,500,500,1500,500,500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,3000,3000, 9000,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,500,500,500,500,500,500,1500,500,1500,500,1500,500,500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,500,500,500,500,500,500,1500,500,1500,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,1500,500,500,500,500,500,500,500,500,500,500,500,1500,500,500,500,500,500,500,500,500,500,500,500,1500,500,1500,500,1500,500,1500,500}; irsend.sendRaw(preraw,2,38); delay(10); irsend.sendRaw(raw,347,38); delay(3000); }
Здесь просто посылается команда на включение каждые три секунды, хотелось бы чтобы по соответствующим условиям (по времени) выполнялась одна из множества команд
Помогите разобраться.
мда. какой странный способ хранить данные
это как вместо того чтобы записать на листке число 500 положить 500 сахарных кубиков, вместо записи 1500 положить 1500 сахарных кубиков и так далее. к концу записи на столе и рядом будет пару тонн сахара вместо пары листков бумаги
Когда мне грусно, я захожу на arduino.ru . Сейчас это бывает часто.
Что ни тема то шедевр: один транзисторы в 220В сует чтобы люминацию устроить, другой >2К портянки в памяти ATmega328P пытается разместить.
Амиго, у ардуинки всего 2К Internal SRAM. 2*1024 = 2048 баЙт. 347*2*3=2082 баЙт. 2082 > 2048, а там еще стек и прочие переменные.
Упс. Придется Вам приложить усилие и заменить портянку на что-то покороче. Там у вас много "500". Замените его чтоли на 500, а вторым числом количество этих 500-к. Ну и
а если сделать проще. записать тоже самое но в виде битов в лонге или любой другой тип данных. если 0 то 500 если 1 то 1500. займет например 20 байт и тоже самое получится
кроме того ещё все числа кратны 100 и не более 25500, разделив все на 100 можно хранить не инты, а байты.
а если сделать проще. записать тоже самое но в виде битов в лонге или любой другой тип данных. если 0 то 500 если 1 то 1500. займет например 20 байт и тоже самое получится
ну у него там 2900, 3000, 9000 есть, но в принципе можно это все учесть.
конечно можно учесть. вообще не проблема
и это ведь 1 кодовая последовательность. а там еще их куча. как он все запихнет? внешнюю память только
кстати что за raw формат данных? 4 или 2 байта?
1. Добавить метод IRsend::sendRawP и поместить массив во Flash. Реализовав в новом методе чтение данных из Flash.
2. Добавить метод IRsend::sendCodeRaw, закодировав последовательность и записав её во Flash
UPD: И вынести массивы из loop, т.е. сделать их глобальными. Это может и не сильно помочь, но в данном коде будет более оптимально. Глобальный массив будет размещен в памяти, а локальный в стеке, хотя как компилятор сделает, я не смотрел, не было нужды.
UPD2: Про short это я загнул, sorry, привык к 64 битным машинам на AIX :) Удалил первый вариант.
1. Добавить метод IRsend::sendRawP и поместить массив во Flash. Реализовав в новом методе чтение данных из Flash.
2. Добавить метод IRsend::sendCodeRaw, закодировав последовательность и записав её во Flash.
Вот можно чуть подробнее на примере кода, не сочтите за труд.
Из лупа конечно массив вынесу.
кроме того ещё все числа кратны 100 и не более 25500, разделив все на 100 можно хранить не инты, а байты.
Это поможет уменьшить размер необходимой оперативки всего лишь вдвое. Мне кажется всё равно не поместиться.
Хотя...для начала мне хватит трёх таких массивов. Вкл, выкл и установка на 16 градусов.
347*2*3=2082 баЙт. 2082 > 2048, а там еще стек и прочие переменные.
А зачем на 3 умножаете ? Вроде как массив из примера 694 байта занимает.
Всё, понял, это вы про мои три кода, с которыми скетч уже не работает
Это поможет уменьшить размер необходимой оперативки всего лишь вдвое. Мне кажется всё равно не поместиться.
Хотя...для начала мне хватит трёх таких массивов. Вкл, выкл и установка на 16 градусов.
Так это я предложил как дополнение метода предложенного выше.
Так это я предложил как дополнение метода предложенного выше.
Про это ? :
"а если сделать проще. записать тоже самое но в виде битов в лонге или любой другой тип данных. если 0 то 500 если 1 то 1500. займет например 20 байт и тоже самое получится".
Да, память действительно сэкономит, но придётся коды опять вручую вбивать.
почему вручную? функцию чтения с ик приемника если переделать на то чтобы формировать лонг сразу
по сути получил сдвинул получил сдвинул. заполнился лонг заполняешь следующий
но тут ведь записывается как выставить 16 градусов например: тоесть набрать на клавиатеру 1+6+установить например
но можно считать коды цифр и потом можно будет просто выставить 20, и для этого не нужно будет считывать всю последовательность именно для 20, а сформировать из последовательности для 2 и 0 и кнопки установить
Для начала, я бы объявил константные массивы как "const". Предполагаю, компилятор сам сообразит, что константные данные можно разместить в программной памяти.
Если не сообразит - в любом компиляторе должны быть ещё какие-то модификаторы-спецификаторы, которые явно управляют размещением данных. Думаю, что так. Но сам искать не буду, лениво мне. :)
А вообще - да, начать надо с правильного формата данных. Тогда и не придётся разбираться с разными компиляторными тонкостями.
Я пытался вначале считывать коды с помощью библиотек IRremote. Но оказалось там есть ограничение в 255 бит на длину записываемых данных. Так что мои 347 бит пришлось считывать и вбивать вручную.
Как считать с ИК датчика посылки в лонг, я с ходу не соображу, да и вообще затрудняюсь, ибо с программированием на вы. Мне бы что попроще.
Подумал было с помощью функции tone() задавать посылки, без использования библиотеки IRremote. Тогда не надо было бы задавать такие большие переменные, а указывать непосредственно в функции tone продолжительность каждой посылки. Но увы, и тут облом, максимальная частота этой функции 32768 Гц, а мне надо 36 000 Гц.
Const пробовал, не вышло. Надо будет ещё покопаться
Еще вариант: "сжать" информацию, т.е. ввести кодирование, рассмотрим на примере:
т.е. сначала значение, потом счетчик, соответственно своим методом "расжимать" данные, выводя их в цикле.
Про чтение из Flash, уж извините, некогда. Ищите, информации море.
А еще, это всё было бы удобно "раскроить", если известны биты и способ кодирования (NEC, RC5 и т.п.), тогда можно было бы генерировать данные налету и массивы стали бы не нужны. Например, код 0x01 налету заменять на:
Впрочем это и сейчас можно разделить посылки и закодировать последовательности битами, что у же и предлагали.
UPD: const - это в ARM, здесь не прокатит.
ну делай тогда как тебе проще
это команда отправки. тип данных поменять можно на byte а все числа поделить на 100 как уже предлагалось, а в отправке нужно домножать
Разобрался с записью и чтением массивов из флэш памяти.
Вроде как всё просто, но из описания Progmema на ардуино.сс это не совсем очевидно.
1. Не забыть указать в начале кода :
#include <avr/pgmspace.h>
Указываем тип данных во временном массиве "raw", в котором будут записываться данные перед отправкой ИК посылки.
Да, он будет размещаться в оперативке, но только он, а не все используемые в скетче массивы.
unsigned int raw[347];
Потом записываем во флэш память все нужные нам массивы, в данном случае это "raw24off" из 347 элементов. Количество и размер массивов ограничены размером флэш памяти микроконтроллера, а не размером оперативки.:
PROGMEM prog_uint16_t raw24off[347] = {
2850,
8950,450,550,450,1500,450,550,450,550,450,550,400,600,400,550,450,550,450,500,500,1500,450,550,450,550,400,1500,500,1500,450,550,450,1500,450,1550,400,1550,450,1550,400,1550,450,550,450,550,450,500,450,550,450,550,450,500,500,500,450,550,450,500,450,550,450,550,450,500,500,500,450,550,450,550,450,550,400,550,450,550,450,550,450,550,450,500,450,550,450,550,450,550,450,500,450,550,450,500,500,500,450,550,450,500,500,550,400,550,450,550,450,550,400,1550,450,1550,450,2950,2900,
8950,450,1500,500,500,450,550,450,550,450,550,400,550,450,500,500,550,400,550,450,1550,450,550,400,600,350,1600,450,500,500,1500,450,1500,450,1500,500,1500,450,1500,500,1500,450,500,500,500,450,550,450,550,400,600,400,550,450,550,450,550,450,500,450,550,450,550,450,550,450,500,450,550,450,550,450,500,500,500,450,550,450,550,450,500,450,550,450,550,400,600,400,550,450,550,450,550,450,500,500,500,450,550,450,550,450,550,400,550,450,550,450,500,500,500,450,550,400,3050,2850,
8950,450,1550,400,600,400,600,400,550,450,550,450,550,450,500,450,550,450,550,450,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,1500,500,500,500,500,500,500,500,1500,500,1500,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,1500,500,500,500,500,500,500,500,500,500,500,500,1500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,1500,500,1500,500};
А непосредственно перед использованием массива считываем из флэши каждый его элемент по отдельности в оперативку во временный массив raw:
for (int k = 0; k < 347; k++)
{
raw[k] = pgm_read_word_near(&raw24off[k]); // Вот что означает "&" не знаю.
}
Теперь можно послать массив raw на ИК диод с помощью стандартной команды:
irsend.sendRaw(raw,347,38);
не ожидал уже что разберешься))
Я и сам не ожидал :)
работает? ведь получается ты хранишь во флеше, но все равно делаешь массив и считываешь с флеша в массив, хотя можешь отправлять без буфера во флеше
правда переделать функцию отправки все равно придется
а если все равно переделывать то может дальше переделать. не храня огромный кусок во флеше с ненужными нулями. но дело твое. сам смотри
Работает.
Проблемы возникают когда в оперативке болтаются три таких массива. А с одним всё в порядке.
Так что я считаю задача выполнена.
Вот скетч, может кому пригодится.
Выполняет режим антизамерзания в помещении при помощи ночного тарифа и посылкой ИК кодов на кондиционер Самсунг серии AQV. Можно забить свои коды от другого кондишена, предварительно считав их любым доступным методом.
При дневном тарифе кондиционер включается только если температура в помещении падает ниже +5. По достижени +8 отключатся.
Ночью поддерживается температура +16.
В недельный таймер из Леруа Мерлена вставляется ардуино нано, датчик DS18x20. И питание ардуины. Силовая начинка из таймера купируется. Вот и всё устройство.
может проглядел. а как ардуина узнает сколько сейчас время?
Ага, проглядел .
"В недельный таймер из Леруа Мерлена вставляется ардуино нано,"
Замечательная штука. И недорогая.
А таймер уже даёт команду на аналоговый вход A0 на включение или выключение по времени.
Силовая начинка из таймера купируется
я подумал вообще все выкинул
...
Бесполезная трата ОЗУ, проще было добавить метод, который отправляет RAW из флеша, было бы быстрее и проще код (не забудешь сделать копию). Хозяин-барин.
Может быть, но гугль информации по этим функциям не дал, а вы не ответили:
1. Добавить методIRsend::sendRawP и поместить массив во Flash. Реализовав в новом методе чтение данных из Flash.
2. Добавить метод
IRsend::sendCodeRaw, закодировав последовательность и записав её во Flash.
"Вот можно чуть подробнее на примере кода, не сочтите за труд."
Поэтому as is...