• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
EEPROM problem
#1
Witam
Oto program generatora z regulacją częstotliwości, problem = EEPROM nie zachowuje wartosci amp.

Kod:
#include <EEPROM.h>
unsigned long amp = 0;
void setup() {

  Serial.begin(115200);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B

  //Enable pin change interrupts on pins 9 and 10 PB 2 and 3
  PCMSK0 |= (1 << PCINT2); //enable interrupt pin 10
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9

  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  GTCCR |= 1 << PSRASY; //reset prescaler

  //+++++++++++++++++++++++++++++++++++++++++
  TCCR1B = (1 << WGM13) + (1 << WGM12) + (1 << CS10); // prescaler = 1 (none)
  //+++++++++++++++++++++++++++++++++++++++++++++

  //ICR1 = 200;//
  //ICR1 = amp;//
  OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
  OCR1B = OCR1A / 2; //offset by half period

  TCCR1B |= _BV(WGM13) | _BV(WGM12); //CTC mode with ICR1
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match

  // EEPROM.get(0, amp);
}

void loop() {
  ICR1 = amp;
  if (digitalRead(A3) == 0) {
    amp++;

    //EEPROM.write(0, amp);
  }
  if (digitalRead(A4) == 0) {
    amp--;
    //EEPROM.write(0, amp);
  }


  Serial.print("amp Hz = ");
  Serial.println(amp);
  // Serial.println(amp/10);

}
 
Odpowiedź
#2
Write jest do zapisu 1 bajta, a chcesz zapisać 4, użyj put/get https://docs.arduino.cc/learn/built-in-libraries/eeprom
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
  EEPROM.get(0, amp);
Gdy jest włączony, cyfry amp pamięta, lecz generator nie produkuje impulsów , jeśli wyłączony impulsy są ale nie ma pamięci.

<> nie działa
 
 
//Write jest do zapisu 1 bajta, a chcesz zapisać 4, użyj put/get
#include <EEPROM.h>
unsigned long amp = 0;
void setup() {
 
  Serial.begin(115200);
  pinMode(A3, INPUT_PULLUP);
  pinMode(A4, INPUT_PULLUP);
  pinMode(9, OUTPUT); //output A
  pinMode(10, OUTPUT); //output B
 
  //Enable pin change interrupts on pins 9 and 10 PB 2 and 3
  PCMSK0 |= (1 << PCINT2); //enable interrupt pin 10
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9
 
  TCCR1A = 0; //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;
  GTCCR |= 1 << PSRASY; //reset prescaler
 
  //+++++++++++++++++++++++++++++++++++++++++
  TCCR1B = (1 << WGM13) + (1 << WGM12) + (1 << CS10); // prescaler = 1 (none)
  //+++++++++++++++++++++++++++++++++++++++++++++
 
  //ICR1 = 200;//
  //ICR1 = amp;//
  OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
  OCR1B = OCR1A / 2; //offset by half period
 
  TCCR1B |= _BV(WGM13) | _BV(WGM12); //CTC mode with ICR1
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match
 
  EEPROM.get(0, amp);
}
 
void loop() {
  ICR1 = amp;
  if (digitalRead(A3) == 0) {
    amp++;
 
    EEPROM.put(0, amp);
  }
  if (digitalRead(A4) == 0) {
    amp--;
    EEPROM.put(0, amp);
  }
  Serial.print("amp Hz = ");
  Serial.println(amp);
//Serial.println(amp/10);
 
}
 
Odpowiedź
#4
Takim sposobem obsługi EEPROM zabijesz go po jednym dniu zabawy. Naucz się korzystać z millis, zarządzać czasem, jakaś biblioteka do obsługi drgań styków przycisku, przycisków po prostu. Wciskasz przycisk to generujesz setki impulsów, od razu próbujesz to zapisać co trwa długo.
Może podziel sobie program na rozdziały, jak zapisujesz do EEPROM to daj mu na to odpowiednio dużo czasu, to powolny proces.
Możesz napisać swoją funkcję zapisu skoro write Ci działa (a lepiej update, czyli odczytuje, sprawdza czy jest sens zapisać dany byte, bo jak jest taki sam to po co, a jak nie to go zmienia), ale nie w każdym obiegu loop, to nie ma sensu robić 16mln x/sekundę, to co się dzieje w aktualnie generowanym powinno się opierać o zmienne z RAM, a co najwyżej taką zmienną można cyklicznie zapisywać do EEPROM, może raz /minutę, a jak częściej to na żądanie (w sensie na konkretne żądanie "zapisz").
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#5
Takim sposobem obsługi EEPROM zabijesz go po jednym dniu zabawy.
EEPROM jest używany tylko po naciśnięciu przycisku ?
 
Odpowiedź
#6
Tak powinno być, choć nawet wtedy sprawny palec potrafi wbić 10Hz, a to oznacza po 3h klikania przekroczenie granicy 100k zapisów, oczywiście hipotetycznie. Zapisując za każdym razem w kolejnej komórce można to zwiększyć x100.
Ale Ty nie zapisujesz gdy jest wciśnięty przycisk, tylko gdy na pinie jest stan 0.
Zamień zapis na wydruk Serial i zobacz jaką wartość Ci wydrukuje po paru flegmatycznych wciśnięciach:
Kod:
void loop() {
static uint16_t zmienna=0;
  ICR1 = amp;
  if (digitalRead(A3) == 0) {
    amp++;
Serial.println(zmienna++);
   // EEPROM.put(0, amp);
  }
  if (digitalRead(A4) == 0) {
    amp--;
Serial.println(zmienna++);
  //  EEPROM.put(0, amp);
  }
 // Serial.print("amp Hz = ");
 // Serial.println(amp);
//Serial.println(amp/10);

}
Mnie drukuje tak 2-3 tysie. Sprawdź, czy masz tak szybkie palce by zejść poniżej 1000.
Zapis do EEPROM jest bardzo wolny, jak już pisałem, ale to z punktu widzenia działania rdzenia 16MHz,  ze 100x na sekundę da radę. Użyj jakieś biblioteki do przycisku, polecam onebutton.
Zwróć uwagę, że w demówkach do EEPROM raczej wszystko jest w setup. Zapis w loop trzeba dobrze przemyśleć.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#7
Narazie jest problem z użyciem eeprom , tutaj używają go w loop.
Kod:
#include <EEPROM.h>
int pinIncrease = 2;
int pinDecrease = 3;
int pinLED = 11;
int pinSetting = 10;
int SpeedFan;
byte laju;
void setup() {
Serial.begin(9600);
pinMode(pinIncrease, INPUT);
pinMode(pinDecrease, INPUT);
pinMode(pinSetting, INPUT);
pinMode(pinLED, OUTPUT);
digitalWrite(pinIncrease, HIGH);
digitalWrite(pinDecrease, HIGH);
}
void loop() {
if(digitalRead(pinSetting) == HIGH){
laju = EEPROM.read(1);
SpeedFan = constrain(SpeedFan, 0, 255);
analogWrite(pinLED, laju);
EEPROM.write(1, SpeedFan);
laju = EEPROM.read(1);
Serial.print(laju);
Serial.print(” “);
Serial.println(SpeedFan);
delay(20); setting();
}else if(digitalRead(pinSetting) == LOW){
laju = EEPROM.read(1);
SpeedFan=laju;
analogWrite(pinLED, laju);
Serial.print(laju);
Serial.print(” “);
Serial.println(SpeedFan);
delay(20);
}
}
void setting(){
if(digitalRead(pinIncrease) == LOW){
SpeedFan++;
}else if(digitalRead(pinDecrease) == LOW){
SpeedFan–;
}
}

Advertisements

REPORT THIS AD
SHARE THIS:
TwitterFacebook

Search

Search for: Search
Advertisements
 
Odpowiedź
#8
To, że ktoś użył nie znaczy, że dobrze.

Działać może i działa, ale kolega kaczakat próbuje Ci powiedzieć, że EEPROM ma ograniczoną ilość zapisów (żywotność). Jeżeli zapis do EEPROM jest w pętli, bardzo często dochodzi do zapisu i pamięć przestaje po prostu działać.

Należy przede wszystkim zastanowić się po co używać zapisu do EEPROM? Zazwyczaj pamięć ta używana jest do zapisu danych, które mikrokontroler musi pamiętać po zaniku zasilania. Podczas normalnej pracy wartości zmiennych zapisywane są w pamięci ulotnej i dopóki urządzenie działa i program jest napisany ok nic im się nie powinno stać.

Do EEPROMu możesz sobie zapisywać np. co 500ms, co 1s albo przy wyjściu z programu. Jeżeli chcesz to robić w pętli prawie bez opóźnień wybierz inny rodzaj pamięci.
 
Odpowiedź
#9
Zmienna amp jest 32bit.
Rejestr ICR1 jest 16bit.
W kodzie masz:

Kod:
ICR1 = amp;

Jedna komórka EEPROM pomieści jeden bajt, więc po pewnych perturbacjach do ICR1 zapiszesz maksymalnie liczbę 8bit, czyli regulacji częstotliwości jakby nie masz.
Do tego flashem szastasz jak byś go miał na pęczki.
Pomyśl nad poradami Kaczakata, oraz zastanów się nad typami zmiennych.
Po lekkiej modyfikacji, kod będzie działał. (przynajmniej u mnie działa)
Do zapisu aktualnej wartości, dodaj sobie oddzielny przycisk, wtedy EEPROM posłuży ci na wieki.
------------------
Sponsorem dzisiejszego wpisu jest hasło: DEBOUNCING.
Jak ktoś mądry napisał - "funkcja nie może zostać uruchomiona, dopóki nie upłynie określony czas bez wywołania tej funkcji."
To się tyczy drgań przycisków, jak i inkrementowania zmiennej amp. Bo gdy wywalisz z loop obsługę seriala, to nawet nie zauważysz jak szybko zmienia się nasza zmienna.
Do tego zastanów się, co się stanie jeśli zmienna osiągnie maksymalną/minimalną wartość dla danego typu, a ty dalej masz wciśnięty przycisk. Musisz zastosować jakieś warunki brzegowe.
-------------------
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości