ПОМОГИТЕ с уменьшением размера кода для Attiny13a
Я делаю отличный рождественский подарок в виде персонализированного печатного значка. Все отлично работает с подключенным uno, но его сердце на самом деле Attiny13a, где я ТОЛЬКО перемещаюсь 1024 байта (в моем коде 1944) 64 байта переменных (мне каким-то образом удалось скопировать несколько вещей при запуске, поэтому я едва добираюсь до 59 байт)
Дело в том, как я могу сделать это еще меньше??
void setup() {
pinMode(3, INPUT_PULLUP);
}
void charlie(int a[])
{
if(a[0] < 0){
pinMode(5, INPUT);
}else
{
pinMode(5, OUTPUT);
digitalWrite(5, a[0]);
}
if(a[1] < 0){
pinMode(6, INPUT);
}else
{
pinMode(6, OUTPUT);
digitalWrite(6, a[1]);
}
if(a[2] < 0){
pinMode(2, INPUT);
}else
{
pinMode(2, OUTPUT);
digitalWrite(2, a[2]);
}
if(a[3] < 0){
pinMode(4, INPUT);
}else
{
pinMode(4, OUTPUT);
digitalWrite(4, a[3]);
}
}
void copy(int* src, int* dst, int len) {
memcpy(dst, src, sizeof(src[0])*len);
}
void resetP()
{
pinMode(5, INPUT);
pinMode(6, INPUT);
pinMode(2, INPUT);
pinMode(4, INPUT);
}
void loop() {
int koz1[4] = {-2,LOW,HIGH,-2};
//int koz2[4] = {-2,HIGH,LOW,-2};
int koz2[4];
copy(koz1, koz2, 4);
koz2[1] = HIGH;
koz2[2] = LOW;
int koz3[4] = {LOW,HIGH,-2,-2};
//int koz4[4] = {HIGH,LOW,-2,-2};
int koz4[4];
copy(koz3, koz4, 4);
koz4[0] = HIGH;
koz4[1] = LOW;
int koz5[4] = {LOW, -2,-2,HIGH};
//int koz6[4] = {HIGH, -2,-2,LOW};
int koz6[4];
copy(koz5, koz6, 4);
koz4[0] = HIGH;
koz4[3] = LOW;
int cap[4] = {-2, HIGH,-2,LOW};
int oko1[4] = {LOW, -2,HIGH,-2};
//int oko2[4] = {HIGH, -2,LOW,-2};
int oko2[4];
copy(oko1, oko2, 4);
oko2[0] = HIGH;
oko2[2] = LOW;
// put your main code here, to run repeatedly:
static long oldTime = 0;
long Ctime = millis();
long diffT = Ctime - oldTime;
oldTime = Ctime;
static bool holdButt = false;
static long holdTime = 0;
static long shortPressATime = 0;
//static long longPressATime = 0;
static bool kozichOn = true;
//charlie(oko1);
//charlie(oko2);
if(digitalRead(3) == LOW)
{
holdButt = true;
holdTime = holdTime + diffT;
}
else if (holdButt && digitalRead(3) == HIGH){
holdButt = false;
if(holdTime > 1000){
//longPressATime = 5000;
kozichOn = !kozichOn;
}
else
{
shortPressATime = 5000;
}
holdTime = 0;
}
if(shortPressATime > 0)
{
shortPressATime = shortPressATime - diffT;
/*charlie(koz1);
charlie(koz2);
charlie(koz3);
charlie(koz4);
charlie(koz5);
charlie(koz6);
charlie(cap);
*/
if(((round(shortPressATime/100) / 2) & 1) == 0){
charlie(oko1);
charlie(oko2);
resetP();
}
else{
}
}
/*
else if (longPressATime > 0)
{
longPressATime = longPressATime - diffT;
charlie(oko1);
delay(5000/longPressATime);
charlie(oko2);
delay(5000/longPressATime);
longPressATime = longPressATime - 5000/longPressATime;
longPressATime = longPressATime - 5000/longPressATime;
}*/
else{
if(kozichOn){
charlie(koz1);
charlie(koz2);
charlie(koz3);
charlie(koz4);
charlie(koz5);
charlie(koz6);
charlie(cap);
}
charlie(oko1);
charlie(oko2);
}
resetP();
}
РЕДАКТИРОВАТЬ: Ребята, вы потрясающие вместе с теми, кто на форумах arduino, похоже, я наконец-то добился этого, я попытаюсь оптимизировать немного больше, так как его 1010 байтов 98%. Но я благодарю вас всех. Вы научили меня за 1 час больше практических вещей, чем я мог прочитать за неделю.
void setup() {
pinMode(3, INPUT_PULLUP);
}
void charlie(byte a[])
{
if(a[0] == 0x0F){
pinMode(5, INPUT);
}else
{
pinMode(5, OUTPUT);
digitalWrite(5, a[0]);
}
if(a[1] == 0x0F){
pinMode(6, INPUT);
}else
{
pinMode(6, OUTPUT);
digitalWrite(6, a[1]);
}
if(a[2] == 0x0F){
pinMode(2, INPUT);
}else
{
pinMode(2, OUTPUT);
digitalWrite(2, a[2]);
}
if(a[3] == 0x0F){
pinMode(4, INPUT);
}else
{
pinMode(4, OUTPUT);
digitalWrite(4, a[3]);
}
}
/*
void copy(int* src, int* dst, int len) {
memcpy(dst, src, sizeof(src[0])*len);
}
*/
/*
void resetP()
{
pinMode(5, INPUT);
pinMode(6, INPUT);
pinMode(2, INPUT);
pinMode(4, INPUT);
}
*/
void loop() {
byte koz1[4] = {0x0F,LOW,HIGH,0x0F};
//int koz2[4] = {null,HIGH,LOW,null};
byte koz2[4];
//copy(koz1, koz2, 4);
memcpy(koz2, koz1, sizeof(koz1[0])*4);
koz2[1] = HIGH;
koz2[2] = LOW;
byte koz3[4] = {LOW,HIGH,0x0F,0x0F};
//int koz4[4] = {HIGH,LOW,2,2};
byte koz4[4];
//copy(koz3, koz4, 4);
memcpy(koz4, koz3, sizeof(koz3[0])*4);
koz4[0] = HIGH;
koz4[1] = LOW;
byte koz5[4] = {LOW, 0x0F,0x0F,HIGH};
//int koz6[4] = {HIGH, 2,2,LOW};
byte koz6[4];
//copy(koz5, koz6, 4);
memcpy(koz6, koz5, sizeof(koz5[0])*4);
koz4[0] = HIGH;
koz4[3] = LOW;
byte cap[4] = {0x0F, HIGH,0x0F,LOW};
byte oko1[4] = {LOW, 0x0F,HIGH,0x0F};
//int oko2[4] = {HIGH, 2,LOW,2};
byte oko2[4];
//copy(oko1, oko2, 4);
memcpy(oko2, oko1, sizeof(oko1[0])*4);
oko2[0] = HIGH;
oko2[2] = LOW;
// put your main code here, to run repeatedly:
static uint16_t oldTime = 0;
uint16_t Ctime = millis();
uint16_t diffT = Ctime - oldTime;
oldTime = Ctime;
static bool holdButt = false;
static uint16_t holdTime = 0;
static uint16_t shortPressATime = 0;
//static long longPressATime = 0;
static bool kozichOn = true;
//charlie(oko1);
//charlie(oko2);
if(digitalRead(3) == LOW)
{
holdButt = true;
holdTime = holdTime + diffT;
}
else if (holdButt && digitalRead(3) == HIGH){
holdButt = false;
if(holdTime > 1000){
//longPressATime = 5000;
kozichOn = !kozichOn;
}
else
{
shortPressATime = 5000;
}
holdTime = 0;
}
if(shortPressATime > 0)
{
shortPressATime = shortPressATime - diffT;
if(((uint16_t(shortPressATime/128) / 2) & 1) == 0){
charlie(oko1);
charlie(oko2);
}
else{
}
}
else{
if(kozichOn){
charlie(koz1);
charlie(koz2);
charlie(koz3);
charlie(koz4);
charlie(koz5);
charlie(koz6);
charlie(cap);
}
charlie(oko1);
charlie(oko2);
}
pinMode(5, INPUT);
pinMode(6, INPUT);
pinMode(2, INPUT);
pinMode(4, INPUT);
}
@Nejcraft hraje, 👍0
Обсуждение2 ответа
Первое, что я бы попробовал, это избавиться от ядра Arduino и вместо этого программировать на avr-libc уровень:
- используйте прямой доступ к порту вместо
digitalRead()
/digitalWrite()
- настройте таймер и измеряйте время в единицах переполнения таймера вместо использования
millis()
.
Кроме того, используйте int8_t
для всех небольших целых чисел (особенно в массивах) и uint16_t
для управления временем, если вам не нужно обрабатывать длительности, превышающие 65 535 единиц времени. .
Обновление: вот моя попытка перевести ваш код на простой C +
avr-libc. Обратите внимание, что, поскольку я не знаю распиновку ядра, вы
используя (что такое контакт 6?), я делаю один. Я также реализовал Мишеля
Предложение Кейзера о включении дублированного кода в функцию,
который я назвал set_pin()
. Полностью не проверено:
#include <stdbool.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#define INPUT 0x0f
#define LOW 0x00
#define HIGH 0x01
// Настройте Таймер 0 на подсчет миллисекунд, предполагая, что F_CPU = 8 МГц.
static void init_timer() {
OCR0A = 125 - 1; // период = 125*64 = 8000 циклов процессора
TCCR0A = _BV(WGM01); // CTC, ВЕРХ = OCR0A
TCCR0B = _BV(CS00) // часы @ F_CPU/64
| _BV(CS01); // то же самое
TIMSK0 = _BV(TOIE0); // разрешаем прерывание по переполнению таймера
}
volatile uint16_t millis_counter;
// Считаем миллисекунды при каждом переполнении таймера.
ISR(TIM0_OVF_vect) {
++millis_counter;
}
// Чтение счетчика миллисекунд, избегая условий гонки.
static uint16_t millis() {
uint16_t millis_counter_copy;
ATOMIC_BLOCK(ATOMIC_FORCEON) {
millis_counter_copy = millis_counter;
}
return millis_counter_copy;
}
static void setup() {
PORTB |= _BV(PB4); // подтягивание на PB4
init_timer();
sei();
}
// Установите вывод как INPUT, LOW или HIGH.
static void set_pin(uint8_t pin_mask, uint8_t state) {
if (state == INPUT) {
DDRB &= ~pin_mask; // ВХОД
PORTB &= ~pin_mask; // без подтягивания
} else {
if (state)
PORTB |= pin_mask; // ВЫСОКИЙ
else
PORTB &= ~pin_mask; // НИЗКИЙ
DDRB |= pin_mask; // ВЫХОД
}
}
static void charlie(uint8_t a[])
{
set_pin(_BV(PB0), a[0]);
set_pin(_BV(PB1), a[1]);
set_pin(_BV(PB2), a[2]);
set_pin(_BV(PB3), a[3]);
}
void loop() {
uint8_t koz1[4] = {INPUT,LOW,HIGH,INPUT};
uint8_t koz2[4];
memcpy(koz2, koz1, sizeof(koz1[0])*4);
koz2[1] = HIGH;
koz2[2] = LOW;
uint8_t koz3[4] = {LOW,HIGH,INPUT,INPUT};
uint8_t koz4[4];
memcpy(koz4, koz3, sizeof(koz3[0])*4);
koz4[0] = HIGH;
koz4[1] = LOW;
uint8_t koz5[4] = {LOW, INPUT,INPUT,HIGH};
uint8_t koz6[4];
memcpy(koz6, koz5, sizeof(koz5[0])*4);
koz4[0] = HIGH;
koz4[3] = LOW;
uint8_t cap[4] = {INPUT, HIGH,INPUT,LOW};
uint8_t oko1[4] = {LOW, INPUT,HIGH,INPUT};
uint8_t oko2[4];
memcpy(oko2, oko1, sizeof(oko1[0])*4);
oko2[0] = HIGH;
oko2[2] = LOW;
static uint16_t oldTime = 0;
uint16_t Ctime = millis();
uint16_t diffT = Ctime - oldTime;
oldTime = Ctime;
static bool holdButt = false;
static uint16_t holdTime = 0;
static uint16_t shortPressATime = 0;
static bool kozichOn = true;
if (bit_is_clear(PINB, PB4))
{
holdButt = true;
holdTime = holdTime + diffT;
}
else if (holdButt && bit_is_set(PINB, PB4)){
holdButt = false;
if(holdTime > 1000){
kozichOn = !kozichOn;
}
else
{
shortPressATime = 5000;
}
holdTime = 0;
}
if(shortPressATime > 0)
{
shortPressATime = shortPressATime - diffT;
if(((shortPressATime/128 / 2) & 1) == 0){
charlie(oko1);
charlie(oko2);
}
}
else{
if(kozichOn){
charlie(koz1);
charlie(koz2);
charlie(koz3);
charlie(koz4);
charlie(koz5);
charlie(koz6);
charlie(cap);
}
charlie(oko1);
charlie(oko2);
}
DDRB &= ~(_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3));
}
int main(void) {
setup();
for (;;)
loop();
}
При компиляции с помощью avr-gcc 5.4.0 я получаю 642 байта флэш-памяти и 31 байт Оперативная память (данные + BSS, не считая стека).
Я предлагаю отказаться от ArduinoIDE и перейти на Atmel Studio. У меня был хороший опыт использования его с USBasp и использования avrdude (поставляется как часть Arduino IDE) для прямой загрузки программы в ATTiny13a., @Filip Franik
Сделал это спасибо, спасибо за предложение, я слышал об этом, но мне это кажется еще сложнее, как будто я знаю С# и аналогичный bcz разработки игр, но idek то, что использует студия atmel, но я попробую это в будущем проект. Еще раз большое спасибо., @Nejcraft hraje
Я попробую ваш перевод, я прототипировал на ардуино, так что должно было быть 0,1,2,4 плексирование 3 - кнопка подтягивания, @Nejcraft hraje
Когда я его компилирую, я получаю:
Sketch uses 2630 bytes (8%) of program storage space. Maximum is 32256 bytes.
Global variables use 64 bytes (3%) of dynamic memory, leaving 1984 bytes for local variables. Maximum is 2048 bytes.
Я удалил все закомментированные строки и изменил целые числа на байты (согласно ответу Эдгара Боне для начала.
Затем я получаю код (добавленный в конце) и следующие результаты:
Sketch uses 2432 bytes (7%) of program storage space. Maximum is 32256 bytes.
Global variables use 24 bytes (1%) of dynamic memory, leaving 2024 bytes for local variables. Maximum is 2048 bytes.
Согласно спецификациям, AtTiny85 имеет 8 КБ памяти программ и 512 байт SRAM, так что вы должны быть в безопасности.
Обратите внимание, однако, если вы хотите подсчитать память SRAM (24 байта, учитываемых IDE), вам также необходимо добавить:
- Байты для глубины вызова функций (например,
loop
вызываетcopy
, а это вызываетmemcpy
, общая память предназначена дляcopy
: + 2 (байт*) + 2 (байт*) + 1 (байт) байт, а для memcpy: + dst (2) + src (2) + sizeof (1) байт. самый «худший» вызов (поэтому проверьте самый глубокий вызов со всеми добавленными аргументами). Все это добавляется в так называемый стек. - Также необходимо добавить стоимость локальных переменных (один раз для каждой функции), так как они также добавляются в стек.
- Если вы используете динамические переменные (malloc), вы также должны их добавить, но это не используется в вашем скетче.
Байты, используемые для элементов с 1 по 3, не упоминаются (поскольку они выделяются во время выполнения).
void setup() {
pinMode(3, INPUT_PULLUP);
}
void charlie(byte a[])
{
if(a[0] < 0){
pinMode(5, INPUT);
}else
{
pinMode(5, OUTPUT);
digitalWrite(5, a[0]);
}
if(a[1] < 0){
pinMode(6, INPUT);
}else
{
pinMode(6, OUTPUT);
digitalWrite(6, a[1]);
}
if(a[2] < 0){
pinMode(2, INPUT);
}else
{
pinMode(2, OUTPUT);
digitalWrite(2, a[2]);
}
if(a[3] < 0){
pinMode(4, INPUT);
}else
{
pinMode(4, OUTPUT);
digitalWrite(4, a[3]);
}
}
void copy(byte* src, byte* dst, byte len) {
memcpy(dst, src, sizeof(src[0])*len);
}
void resetP()
{
pinMode(5, INPUT);
pinMode(6, INPUT);
pinMode(2, INPUT);
pinMode(4, INPUT);
}
void loop() {
byte koz1[4] = {-2,LOW,HIGH,-2};
byte koz2[4];
copy(koz1, koz2, 4);
koz2[1] = HIGH;
koz2[2] = LOW;
byte koz3[4] = {LOW,HIGH,-2,-2};
byte koz4[4];
copy(koz3, koz4, 4);
koz4[0] = HIGH;
koz4[1] = LOW;
byte koz5[4] = {LOW, -2,-2,HIGH};
byte koz6[4];
copy(koz5, koz6, 4);
koz4[0] = HIGH;
koz4[3] = LOW;
byte cap[4] = {-2, HIGH,-2,LOW};
byte oko1[4] = {LOW, -2,HIGH,-2};
byte oko2[4];
copy(oko1, oko2, 4);
oko2[0] = HIGH;
oko2[2] = LOW;
static long oldTime = 0;
long Ctime = millis();
long diffT = Ctime - oldTime;
oldTime = Ctime;
static bool holdButt = false;
static long holdTime = 0;
static long shortPressATime = 0;
static bool kozichOn = true;
if(digitalRead(3) == LOW)
{
holdButt = true;
holdTime = holdTime + diffT;
}
else if (holdButt && digitalRead(3) == HIGH){
holdButt = false;
if(holdTime > 1000){
//longPressATime = 5000;
kozichOn = !kozichOn;
}
else
{
shortPressATime = 5000;
}
holdTime = 0;
}
if(shortPressATime > 0)
{
shortPressATime = shortPressATime - diffT;
if(((round(shortPressATime/100) / 2) & 1) == 0){
charlie(oko1);
charlie(oko2);
resetP();
}
else{
}
}
else{
if(kozichOn){
charlie(koz1);
charlie(koz2);
charlie(koz3);
charlie(koz4);
charlie(koz5);
charlie(koz6);
charlie(cap);
}
charlie(oko1);
charlie(oko2);
}
resetP();
}
На самом деле я использую Attiny13a, у которого всего 1024 байта, с помощью форума arduino я получил отличные 1218 байт, что очень близко к цели, теперь я попытаюсь реализовать это. РЕДАКТИРОВАТЬ: с вашим улучшением я очень близок к 1074 байтам., @Nejcraft hraje
Значит нужно уменьшить размер кода (Flash), а не SRAM? Это две разные вещи., @Michel Keijzers
Извините, но я вернулся к проблеме, мне нужно различать 3 значения, и когда я использую байты, мне нужно изменить функцию, чтобы она была ifs (== 2), но затем я вернулся к 1246, @Nejcraft hraje
Не уверен, что вы говорите (также я думаю, вы не дали ответа) ... Вы можете скопировать дублированный код в одну функцию и вызвать ее с параметрами, что сэкономит вам немного места во флэш-памяти., @Michel Keijzers
Сделай это. Спасибо, @Nejcraft hraje
Добро пожаловать ... если вы считаете ответ полезным, проголосуйте за него (нажмите стрелку вверх рядом с вопросом); если вы считаете, что ответы решили вашу проблему, также примите их (нажмите галочку рядом с ответом). Удачи с вашим проектом., @Michel Keijzers
@eternaldownvoter: пожалуйста, напишите, что можно улучшить., @Michel Keijzers
- Как уменьшить размер скетча?
- Оптимизация кода для использования меньшего количества флэш-памяти и SRAM
- Оптимизация кода для ATtiny10
- Помогите уменьшить размер скетча!
- Нужно ли уменьшать размер библиотек?
- Есть ли константа препроцессора для размера памяти
- Самый простой способ подсчитать, сколько глобальных переменных содержится в коде скетча?
- Как удалить неиспользуемую функцию в стандартной SD-библиотеке Arduino, чтобы уменьшить размер скетча?
какова желаемая функциональность?, @jsotola