Memória do Mega cheia

Boas pessoal.

Eu estou a trabalhar com o MEGA para desenvolver um programa que tem implementados 'alguns' arrays de valores. A situação é que quando eu tenho algumas variaveis declaradas como locais, a memória ocupada é substancialmente menor aquela que verifico quando declaro essas mesmas variaveis fora de uma função, ou seja, passando elas a ser globais do programa. Agora, que continuei a programar, a cada ciclo if ou for que implemento, mesmo por muito 'pequeno' que ele seja (poucas linhas de código), a memória do arduino aumenta mesmo muito. Anteriormente nao verificava nada semelhante quando implementava todo o restante codigo. Acho isto um bocado estranho e não sei se haverá forma de contornar isto. Tinha um UNO e tive de mudar para um MEGA. Como estou a usar e a endereçar muitos arrays, não sei se poderá ser isto que esteja a encher-me a memória da controlador.

Esse 'alguns'... é que é interessante nesta conversa. Isso e o código... sem eles nada se pode fazer, não te parece?

Sem o código fica difícil de ajudar.

aqui está o código.

Intervalos_teste11.ino (72.8 KB)

Que sabes de programação? E mais concretamente, das limitações do Arduino?

Eu nem contei os arrays nem os tamanhos... mas parecia gigantesco e muito provavelmente não deve funcionar muito bem.

Tendo em conta que estás a usar probabilidades, assumo que os numeros sejam sempre menores que 101, logo podes trocar o tipo de dados int por "unsigned char" e automaticamente reduzes o tamanho de memória usada para metade. Nota que a memória que eu estou a falar é RAM, não flash uma vez que não meteste lá os teus arrays.

Vou fazer essa troca de endereçamento e tentar ganhar mais algum espaço na memória.

Já coloquei todos os 'print' na flash.

Falaste em colocar os arrays na flash, sabes dizer-me onde posso encontrar informação para fazer isso?

Thanks

Fiz aqui umas contas com o compilador…

Portanto, tu tens, da forma que meteste aqui o programa um total de 18294 bytes de memória de programa, ou seja, todas as variáveis em memória.

Ao colocar todas as variáveis em Flash (nota que ao fazer isso, não as podes alterar), o programa passa para 36146 bytes.

Isto quer dizer que os teus arrays ocupam qualquer coisa como 17852 bytes. o Arduino tem 8k de RAM… logo a minha questão é: Isto alguma vez funcionou ou correu no chip?

Ao alterares o tipo de dados como disse, para unsigned char o tamanho ocupado seria reduzido para metade, ou seja, 8926… mesmo assim não funciona.

Para meteres os dados na Flash, fazes assim:

Colocas isto no topo:

#include <avr/pgmspace.h>

E defines os teus arrays assim:

prog_int8_t Primavera_D_prob_iluminacao[96] PROGMEM = {10, 30, 100, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 10, 10, 10, 10, 10};

Tens aqui uma explicação: http://arduino.cc/en/Reference/PROGMEM

Mas mais importante de tudo, o que pretendes atingir com isto? E porque motivo tens tantos arrays? Não haverá uma maneira melhor? Queres explicar a ver se alguém te pode orientar para algo mais… realista?

Sim isto já correu. Para correr novamente basta fazer uma pequena alteração e o MEGA funciona na perfeição.

Pois, bem, dado isto, os meus arrays são o que me estão a consumir a maior parte da memória. Se os passar para a flash vou ter um outro problema que se prende com o aceder aos diferentes valores nas diferentes posições dos mesmos. Pelo que vi na PROGMEM, não é propriamente fácil faze-lo..penso que só mesmo com ponteiros poderia aceder aos dados.

Este código, com tantos arrays, tem a ver com o processo inicial de uma tese de Mestrado, posteriormente ainda ficará algo mais 'pesado' mas, por agora, esses mesmos arrays simulam variáveis que na realidade existem e que, desta forma, estou a simular em código.

Como me elucidaste, se eu declarar os meus arrays como unsigned char eles ficarão assim:

unsigned char Primavera_D_prob_iluminacao[96]  = {10, 30, 100, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 30, 5, 10, 50, 70, 10, 50, 80, 20, 10, 10, 10, 10, 10, 10};

À semelhança dos arrays poderei transportar e aplicar esta alteração para as diversas váriaveis que declarei como int correcto?

Obrigadão aí pela ajuda ;)

Um array é um ponteiro... logo não tens de estar a pensar nisso.

Tou a pensar usar uma Shield para SD card. Usando este método será que posso libertar algum espaço da RAM do Arduino gravando variáveis no cartão de memória?

Eu não faria isso... ao meteres um cartão SD, perdes tempo a aceder e gastas memória RAM para acederes à memória do SD. Da última forma que eu te expliquei, para teres os dados em flash, não devias ter problema algum e deves ficar com mais memória livre do que se estiveres a usar um SD card.

Explicares o que pretendes, por norma, permite-nos ajudar-te um pouco mais...

A situação é, como já falei, o uso de muitos arrays no código. Quando faço a leitura dos diversos valores dos arrays a minha memória vai-se enchendo de forma rápida, chegando a um ponto em que quando faço upload para o MEGA este fica com o led do pino 13 a piscar. Penso que este piscar esteja relacionado com o ultrapassar da memória RAM.

Falaste-me na PROGMEM e eu já enderecei os meus arrays dessa forma e quando compilo, o tamanho do programa é o mesmo do que com o endereçamento directo anteriormente efectuado. Depois deste endereçamento obtive alguns problemas com a leitura dos valores nas diferentes posições dos arrays. Em nenhum dos casos o valor retornado foi aquele que deveria ter sido. Possivelmente terei algum problema com esta parte do código.

Depois disto lembrei-me de poder usar um micro SD mas decidi perguntar aqui se isso seria vantajoso ou mais problemático ainda.

Contudo, pesquisei e encontrei uma livraria que pode ajudar-me. http://arduiniana.org/libraries/flash/comment-page-3/#comment-105688

Se quiseres ver o código para te situares melhor com o problema posso colocá-lo aqui.

Obrigado

Se com e sem o PROGMEM o seu programa está com o mesmo tamanho, você está com algum problema com o PROGMEM. Tenta fazer um exemplo bem simples, só para verificar se o compilador está funcionando bem com o PROGMEM.

Coloca aqui o código...

Eu testei a instrução que deixei aqui para ti e estava a funcionar, logo há qualquer coisa que não está correcta. Mete o código aqui e a gente vê.

Quando pedi para explicares o que estás a fazer não me referia a dizeres que tens um problema com muitos arrays... referia-me a explicares o que o teu programa vai fazer para que a gente te possa indicar outra maneira de fazer isto sem uma quantidade ridícula de variáveis. Nota que se por algum motivo o programa não estiver a fazer o que pretendes, vais passar um mau bocado para descobrir o que se passa de errado.

O código tem como objectivo simular a actuação de dadas saídas em função de uma conjugação de variáveis. Variáveis essas que serão relacionadas com a probabilidade de, em cada instante, uma ou várias saídas serem ou não accionadas.

O código está colocado em anexo.

Intervalos_teste11.ino (75 KB)

Esses arrays ficarão com estes valores que você colocou ou ainda terão alguma modificação? Pergunto isso porque notei que int Outono_S_prob_iluminacao[] int Outono_U_prob_iluminacao[] int Inverno_U_prob_iluminacao[]

Possuem os mesmos valores. Provavelmente outras variáveis terão o mesmo conteúdo. Como parece que o código não faz alterações nesses arrays, pode-se cortar as repetições.

Matematicamente é possível saber o valor de um array através de outro array? Se for possível, você poderá cortar alguns arrays e utilizar a matemática quando for saber seus valores.

Abraços

Não, neste momento apenas estão definidos com os mesmos valores unicamente por questões de testes e verificações de funcionamento. Posteriormente serão definidos e introduzidos valores representativos de uma variável real.

Contudo, já consegui melhorar um pouco o código e ganhei algum espaço em memória. Obrigado a todos.

Rafa

Vi agora o código e não funciona porque falta lá basicamente tudo... :| Tens de incluir o progmem, tens de definir as variáveis com o tipo que eu defini no meu exemplo e também colocar PROGMEM na inicialização.

Estou com o msm problema, será que poderiam me ajudar???

Acredito que a memoria ram esteja cheia tb.

tentei usar o progmem e msm assim não deu certo

#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>
#include <ArdOSC.h> //inclui blibioteca ArdOSC
#include <Wire.h>
#include <avr/io.h>
#include <avr/interrupt.h>

int RECV_PIN = 11;
int ON = 0;

IRrecv irrecv(RECV_PIN);
decode_results results;
#define DETECT 2 //zero cross detect
#define GATE1 8 //triac gate
#define GATE2 12//triac gate
#define PULSE 4 //trigger pulse width (counts)
int i=513;
int j=513;
int led = 13;

byte myMac={ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //define MAC para shield Ethernet
byte myIp = { 192, 168, 0, 99 }; //define IP da central automação
int serverPort = 8000; //define a porta de recepção do comando OSC
int destPort= 9000; //define a porta de envio do comando OSC

OSCServer server; //inicializa o servidor OSC (serviço que trata a recepção de mensagem OSC)
OSCClient client; //inicializa o cliente OSC (serviço que trata o envio de mensagem OSC)

unsigned int TVCABO_POWER[20] = {6050,1200,1200,1150,650,550,650,550,650,1150,650,550,650,550,650,1150,650,1150,650,};
unsigned int TVCABO_MENU[20] = {6050,1150,1200,1200,600,600,600,600,1200,550,650,550,650,550,1250,550,1200,600,600,};
unsigned int TVCABO_GUIA[20] = {6000,1200,1150,1200,650,550,650,550,1250,550,1250,550,650,550,650,550,650,550,650,};
//unsigned int TVCABO_VOLUME_MAIS[20] PROGMEM = {5950,1250,1250,1150,650,550,650,1150,650,1150,1200,600,600,1150,650,550,1250,1150,650,};
//unsigned int TVCABO_VOLUME_MENOS[20] PROGMEM = {6050,1150,1250,1150,650,550,650,1150,600,1200,1200,600,600,1200,600,600,1200,1200,600,};
//unsigned int TVCABO_CANAL_MAIS[20] PROGMEM = {6050,1150,1200,1200,600,550,650,550,650,550,1250,1150,600,1200,1200,600,1200,600,600,};
//unsigned int TVCABO_CANAL_MENOS[20] PROGMEM = {6000,1200,1200,1200,600,600,600,550,650,550,1250,1150,1250,550,1250,550,1250,1150,650,};
unsigned int TVCABO_ESQUERDA[20] = {6100,1150,1200,1150,650,550,650,550,1250,550,600,600,1200,1200,1200,1200,600,1200,600,};
unsigned int TVCABO_DIREITA[20] = {6000,1200,1150,1250,600,600,550,650,1150,650,550,1200,650,550,1200,1200,650,1150,600,};
unsigned int TVCABO_CIMA[20] = {6050,1150,1250,1150,650,550,650,550,1200,600,650,550,650,1150,1200,600,1200,1150,650,};
unsigned int TVCABO_BAIXO[20] = {6050,1150,1200,1200,600,600,650,550,1250,550,650,550,1250,550,1200,1200,600,600,600,};
unsigned int TVCABO_OK[20] = {5950,1250,1200,1200,600,600,600,600,1250,500,650,1150,650,1150,1250,1150,1200,600,650,};
unsigned int TVCABO_1[20] = {6050,1150,1200,1200,600,600,600,600,600,600,600,550,650,1150,650,550,650,1150,650,};
unsigned int TVCABO_2[20] = {6050,1150,1200,1200,600,550,650,550,650,550,600,600,1200,600,600,600,1200,600,600,};
unsigned int TVCABO_3[20] = {6050,1150,1250,1150,650,550,650,550,650,550,650,550,1250,1150,600,600,1200,1200,600,};
unsigned int TVCABO_4[20] = {6050,1150,1250,1150,650,550,650,550,650,550,650,1150,650,550,650,550,1250,1150,600,};
unsigned int TVCABO_5[20] = {6050,1150,1150,1250,550,650,600,600,600,600,600,1200,600,1200,600,1200,600,550,650,};
unsigned int TVCABO_6[20] = {6050,1150,1250,1150,650,550,650,550,650,550,650,1150,1250,550,650,1150,650,1150,600,};
unsigned int TVCABO_7[20] = {6050,1150,1150,1250,550,650,600,600,600,600,600,1200,1200,1150,600,1200,1250,550,650,};
unsigned int TVCABO_8[20] = {6050,1200,1200,1200,600,550,650,550,650,550,1250,550,650,550,650,1150,1250,550,650,};
unsigned int TVCABO_9[20] = {6050,1200,1200,1150,650,550,650,550,600,600,1200,600,600,1200,600,1200,1200,1200,550,};
unsigned int TVCABO_0[20] = {6050,1200,1150,1200,600,600,650,550,650,1150,600,600,600,1200,650,1150,1200,600,600,};
unsigned int TVCABO_SAIR[20] = {6050,1150,1250,1150,600,600,600,600,1200,600,600,1200,1200,600,1200,1200,1200,1150,650,6050,};

IRsend irsend;
String readString;

void setup(){

Serial.begin(9600);
// set up pins
pinMode(DETECT, INPUT); //zero cross detect
digitalWrite(DETECT, HIGH); //enable pull-up resistor
pinMode(GATE1, OUTPUT); //triac gate control
pinMode(GATE2, OUTPUT); //triac gate control
pinMode(led, OUTPUT);
irrecv.enableIRIn(); // Start the receiver

// set up Timer1
//(see ATMEGA 328 data sheet pg 134 for more details)
OCR1A = 100; //initialize the comparator
OCR1B = 100;

TIMSK1 = 0x03; //enable comparator A and overflow interrupts
TCCR1A = 0x00; //timer control registers set for
TCCR1B = 0x00; //normal operation, timer disabled

// set up zero crossing interrupt
attachInterrupt(0,zeroCrossingInterrupt, RISING);

//IRQ0 is pin 2. Call zeroCrossingInterrupt
//on rising signal

Ethernet.begin(myMac ,myIp); //inicializa a interface ethernet
server.begin(serverPort); //inicializa o servidor OSC definindo a porta de RX
//set callback function & oscaddress

}

void loop()
{
if(server.aviableCheck()>0){ //verifica se existe alguma mensagem OSC disponível para leitura
}

OCR1A = i; //set the compare register brightness desired.
OCR1B = j;
}

void func23(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_POWER,20,38);
}

void func24(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_GUIA,20,38);
}

void func25(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_MENU,20,38);
}

void func26(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_ESQUERDA,20,38);
}

void func27(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_DIREITA,20,38);
}

void func28(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_CIMA,20,38);
}

void func29(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_BAIXO,20,38);
}

void func30(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_OK,20,38);
}

void func31(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_1,20,38);
}

void func32(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_2,20,38);
}

void func33(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_3,20,38);
}

void func34(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_4,20,38);
}

void func35(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_5,20,38);
}

void func36(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_6,20,38);
}

void func37(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_7,20,38);
}

void func38(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_8,20,38);
}

void func39(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_9,20,38);
}

void func40(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_0,20,38);
}

void func41(OSCMessage *_mes){ ///TVCABO/POWER
irsend.sendRaw(TVCABO_SAIR,20,38);
}

void func42(OSCMessage *_mes){ //rotina que trata comando OSC “/ard/led2” recebido do ANDROID
int value=(int)_mes->getArgFloat(0); //armazena em “value” o argumento do comando OSC “/ard/led2”
i = value;
}

void func43(OSCMessage *_mes){ //rotina que trata comando OSC “/ard/led2” recebido do ANDROID
int value=(int)_mes->getArgFloat(0); //armazena em “value” o argumento do comando OSC “/ard/led2”
j = value;
}

void func44(OSCMessage *_mes){ //rotina que trata comando OSC “/ard/led2” recebido do ANDROID
int value=(int)_mes->getArgFloat(0); //armazena em “value” o argumento do comando OSC “/ard/led2”
digitalWrite(led,value);
}

void zeroCrossingInterrupt(){ //zero cross detect
TCCR1B=0x04; //start timer with divide by 256 input
TCNT1 = 0; //reset timer - count from zero
}

ISR(TIMER1_COMPA_vect){ //comparator match
digitalWrite(GATE1,HIGH); //set triac gate to high
digitalWrite(GATE2,HIGH); //set triac gate to high
TCNT1 = 65536-PULSE; //trigger pulse width
}

ISR(TIMER1_OVF_vect){ //timer1 overflow
digitalWrite(GATE1,LOW); //turn off triac gate
digitalWrite(GATE2,LOW); //set triac gate to high
TCCR1B = 0x00; //disable timer stopd unintended triggers
}

Quer erro é que o progmem te dá? Estás a usá-lo correctamente??