Autolaturi mökille varavoimaksi Arduinon avulla

tosin tollasella systeemillä et voi käyttää ehkä esim monitoria joka vaatii 12v koska autosähkössä 12v on vain nimellisjännite ja todellisuudessa moottorin käydessä sen 13,8-14.4v uskoisin että autosähkökäyttöön olevat vehkeet kestää sen 16v vielä helposti, ja jos jotain elektroniikkaa pitää ajaa regu siellä olisi oltava.ja joo kyllä siellä pitäisi olla logiigga joka ei anna sammutus funktion ajaa pwm 100 jos moottori käy
 
@ississ, Joo tuohan oli hyvä. Eli periaatteessa kolmelta anturilta ikään kuin tuossa vahvistus ennen kuin palautetaan akkujännite lataussäätimeen.

Kysyit, että mitä muita laitteita järjestelmässä on. On perus mökkivarusteita: aurinkolataussäädin, radio, lamppuja, jääkaappi, tarpeen mukaan erikseen päälle kytkettävä 230 V invertteri.

Jääkaape on ainakin tarkoitettu karavaanikäyttöön, joten siinä ainakin lienee jännitteen yläraja korkeampi.
 
@TemeV , mutta voiko jännite kuitenkin nousta 16 volttiin? Miten käy laitteille, jotka kytkettynä systeemiin, jossa jännite hetkellisesti 16 volttia?
Ei sen pitäisi pystyä noin korkealle hyppäämään sekuntien aikaskaalassa. Jos mietitään että latausvirta olisi vaikkapa 50A normaalisti. Jos saisit jollain erikoisella vikatilanteella nostettua vaikkapa 150 ampeeriin, akku latautuu ja jännite nousee siinä kahdessa sekunnissa saman verran kuin normaalisti kuudessa sekunnissa Eli ei juurikaan.

Johtojen resistanssit toki nostaa jännitettä laturin päässä ja siellä päässä saatettaisiin jo lähennellä sitä 16 volttia, riippuen johtojen paksuudesta ja liitosten laadusta. Jos kuitenkin laitteet on kytketty akkuun, eikä suoraan laturiin, ei ne näe sitä jännitettä. Akun resistanssi lienee joitain milliohmeja, ja tuo 150 ampeeria nostaisi siis jännitettä joitain satoja millivoltteja.
 
@TemeV , no tuolla perusteella, jos siis saa laitettua tuommoisen lisäturvapiirin katkaisemaan ohjauksen laturilta, niin riittäisi aivan ok tämän systeemiin suojaukseksi. Toki silti kannattaa tuossa nuo @ississ :n aiemmin mainitsemat jutut laittaa sinne koodiin.

Täytyy toki muistaa, että varmaan todennäköisyys tämmöiselle tapahtumalle on lähellä nollaa, mutta ei sitä varmaan liian varovainen tässä olla.
 
Tähän väliin sujuvasti koodikysymys taas. Voiko tuossa ajastuksissa käyttää tuota samaa lastTime -muuttuja vai pitääkö kaikille ajastuksille olla omat? Yritän saada noita delay() funktioita pois tuosta koodista, että olisi "nätimpi" koodi.

Näyttääkö toimivalta äkkiseltään katsottuna:

C++:
void shutDown() {  //engine shutdown, execute relay

  //If the charging current drops to 0 to 5 amperes and charging voltage is under 15 volts (safety) and motor is running
  // start the shutdown function and turn off the relay
  if (current >= 0 && current < 5 && sensVoltage < 15 && digitalRead(motorPin) == HIGH && motorStatus == 2) {
    digitalWrite(relayPin, LOW);

    if (millis() - lastTime >= 2000) {  //wait at least 2 seconds to engine stall down

      analogWrite(pwmPin, 255);  // Stop Duty Cycle at 100 %, alternator electromagnet off

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Sammutus");

      motorStatus = 3;  //motor has run, to reset, switch power off, on next startup, it will be reset

#ifdef DEBUG
      Serial.println("Sammutettu.");
#endif
    }

  } else if (motorStatus == 2) {
    lastTime = millis();

    digitalWrite(relayPin, HIGH);  //else, keep relay on

#ifdef DEBUG
    Serial.println("Kaynnissa.");
#endif
  }
}
 
Viimeksi muokattu:
En nyt oo varma mutta jos tuo lasttime oon ns geneerinen muuttuja jota siis käytetään monessa void jotain se käsittääkseni pitäisi myös joka loop kierroksella päivittää tai se päivittää vain kun joku ajaa tuon
Koodi:
lastTime =millis();

jos sulla on void loop()

{

lastTime = millis();


}
niin silloin joka loop kierroksella sulla on tuo arvo johon voit verrata onko aika kulunut. mutta nyt pähkäilen kun tuossa esimerkissä päivität vain lastTimen jos motorstatus == 2 joten jos tuon lisää looppiin rikkooko se jonkun logiigan ? jos rikkoo niin teet toisen esim generallastmillis = millis(); johon vertaa yleismailmallisesti paljonko aikaa on kulunut.
 
Tähän väliin sujuvasti koodikysymys taas. Voiko tuossa ajastuksissa käyttää tuota samaa lastTime -muuttuja vai pitääkö kaikille ajastuksille olla omat? Yritän saada noita delay() funktioita pois tuosta koodista, että olisi "nätimpi" koodi.

Näyttääkö toimivalta äkkiseltään katsottuna:

C++:
void shutDown() {  //engine shutdown, execute relay

  //If the charging current drops to 0 to 5 amperes and charging voltage is under 15 volts (safety) and motor is running
  // start the shutdown function and turn off the relay
  if (current >= 0 && current < 5 && sensVoltage < 15 && digitalRead(motorPin) == HIGH && motorStatus == 2) {
    digitalWrite(relayPin, LOW);

    if (millis() - lastTime >= 2000) {  //wait at least 2 seconds to engine stall down

      analogWrite(pwmPin, 255);  // Stop Duty Cycle at 100 %, alternator electromagnet off

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Sammutus");

      motorStatus = 3;  //motor has run, to reset, switch power off, on next startup, it will be reset

#ifdef DEBUG
      Serial.println("Sammutettu.");
#endif
    }

  } else if (motorStatus == 2) {
    lastTime = millis();

    digitalWrite(relayPin, HIGH);  //else, keep relay on

#ifdef DEBUG
    Serial.println("Kaynnissa.");
#endif
  }
}

Samaa muuttujaa voi käyttää jos ei ole vaaraa että eri viiveet menee päällekkäin.
Tarkoittaa siis sitä että todennäköisesti joillakin muilla muuttujilla pitää tallentaa tilatieto missä ollaan ja sen mukaan tulkita ajastuksia.

Seurannan kannalta voisi olla parempi määrittää nuo motorstatus- arvot nimillä eikä numeroilla. Koodina ihan sama asia mutta silmälle helpompi kun ei tarvitse muistaa mikä tila oli 2 ja mikä 3.
Esimerkiksi

#define MOTOR_OFF 0
#define MOTOR_STARTING 1
#define MOTOR_RUNNING 2
#define MOTOR_STOPPING 3

ja koodissa:

int motorStatus = MOTOR_OFF;

Ja muista varmistaa että tilat/ehdot ovat sellaisia ettei mene vahingossa ohi tai suoriteta liian monta kertaa.
Oikeastaan niin että kun ehto täyttyy niin tila vaihtuu ja silloin on muut ehdot, tarvitset siis ainakin "ajossa" -> "sammumassa" -> "sammutettu" jolloin ajossa tutkitaan virtarajat jne.
Kun pitää aloittaa sammutus niin silloin asettaa lastTime, sammutusrele, jne ja seuraava tila.
"Sammumassa"- tilassa sitten tutkitaan sitä aikaa eikä enää välitetä virroista (ehkä kannattaa asettaa myös pwm minimiin edellä) ja taas asetetaan seuraava tila kun aikaraja täyttyy.

Näin varmistat myös sen että lastTime (tai muu vastaava) joka tässä on "tapahtuman alkuhetki" päivittyy vain tilan vaihdossa silloin kun kyseinen tapahtuma oikeasti alkaa.
Asettamalla jokaisella kierroksella lastTime = millis() kun kone on käynnissä on tavallaan ihan turhaa ja varsinkin silloin sitä ei voi uusiokäyttää.

Jotain tähän tyyliin siis. Ei takeita toiminnasta.
C++:
void shutDown() {

  if ( motorStatus == MOTOR_RUNNING ) {
    // Käynnissä
    if ( ( current >= 0 ) && ( current < 5 ) && ( sensVoltage < 15 ) && ( digitalRead(motorPin) == HIGH ) ) {
      //  ehdot täyttyy -> pitää sammuttaa

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Sammutus alkaa");

#ifdef DEBUG
      Serial.println("Sammutus alkaa");
#endif
      // Ehkä myös tämä
      //analogWrite(pwmPin, 15);  // 5% pwm
      digitalWrite(relayPin, LOW);
      motorStatus = MOTOR_STOPPING;
      lastTime = millis();
    }
  } else if ( motorStatus == MOTOR_STOPPING ) {
    // Sammutus menossa
    if ( ( millis() - lastTime ) >= 2000 ) {
      // Aika täynnä

      if ( [ tähän rpm/tärinä luku -> onko moottori oikeasti sammunut ? ] ) {
        // Ehkä varmuuden vuoksi tarkastaa latausvirta ja jännite myös ennen pwm- asetusta
        // Sammunut
        analogWrite(pwmPin, 255);

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Sammutettu");

#ifdef DEBUG
        Serial.println("Sammutettu");
#endif
        motorStatus = MOTOR_OFF;
        // Sammutusrele pitäisi voida palauttaa jo tässä (koska tarkastettu että sammui)
        // tai sillä missä pitäisi olla silloin kun tehdään seuraava startti.
        //digitalWrite(relayPin, HIGH);
      }
    }
  }

}
 
No niin, eilisen ja tämän päivän aloin tuota koodia ähräämään ja löysin muutamankin ajastinkirjaston, kun en vieläkään tajua tuota millis() funktion käyttöä sen sijaan, että käyttäisi yksinkertaista, mutta muun toiminnan pysäyttävää delay() -funktiota. Löysin kirjastot BlockNot ja Neotimer, josta jälkimmäisen sain nähtävästi toimimaan tekoälykoodin avustuksella.

Periaatteessa tuossa BlockNotissa olisi kai vielä yksinkertaisempi käyttö ollut, mutta jotain siinä missasin, kun funktio suoritettiin heti. Varmaankin ajastin lähti käyntiin aina heti koodin alussa kutsumisesta, mutta Neotimerin avulla siis nyt näyttäisi nuo aikapohjaiset jutut toimivan ilman, että mikään muu keskeytyy. Tämän näkee hyvin sarjaportin tulosta, että tilat vaihtuvat hienosti ajastimen mukaan.

Sen verran tässä on jo kuitenkin "osannut", että pystyy nyt liittämään koodia, ilman että punaista tekstiä on ruutu täynnä! ;)

P.S. Tuskinpa tämä nyt näin meni, sanoo perus pessimisti. Vielä pitää testata, ja katsoa, mikä on esim. ulostulo, toimiiko PWM-portaat odotetusti. ;)

C++:
#define DEBUG  //Serial debug, comment to disable
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#include <neotimer.h>  //Timer from Neotimer library
Neotimer motorTime = Neotimer(6000);  // 6 second timer for startup detection
Neotimer stepTime = Neotimer(1000);   // 1 second timer for PWM step interval
Neotimer shutTime = Neotimer(2000);   // 2 second timer for engine shutdown (wait before switching PWM back to 100 %, electromagnet off)

LiquidCrystal_I2C lcd(0x27, 16, 2);  // Create a new LiquidCrystal_I2C display object with the correct I2C address and display size

// Define the pins
const int currentPin = A0;             //information about current
const int voltagePin = A2;             //information about voltage
const int motorPin = 2;                //motor running pin, HIGH = motor running, TEST purpose LOW
const int pwmPin = 9;                  //PWM output pin
const int relayPin = 4;                //Relay control pin
float voltageFactor = 5.00 / 1023.00;  //Factor to convert ADC reading to voltage

// Define the points for current calculation / the line equation
float x1 = 0.500;  // volts
float y1 = 0;      // amps
float x2 = 4.005;  // volts
float y2 = 150;    // amps
// Calculate the slope and intercept
float m = (y2 - y1) / (x2 - x1);
float b = y1 - m * x1;
float currentCal = 1;  // Variable to shift the whole current level
float sensVfactor = 20.00 / 4.9248;  //4.9248 volts = 20 volts, factor to convert high voltage to 0-5 V
float current;                       //store current value
float sensVoltage;                   //store sensed voltage
const int N = 25;                    //number of current readings to average
const int Y = 25;                    //number of sensed voltage readings to average
int readings[N];                     //array to store the current readings
int readingsV[Y];                    //array to store the sensed voltage readings
int motorStatus;                     //0=stopped, 1=starting, 2=running, 3=stopped but did run, on status 3, just switch off and on again to go back 0
int pwmValues[] = { 24, 41, 58, 77 };  // PWM duty cycle steps, 77 = ~30 %
int currentPwmStep = 0;
// int lcdStep;                      //0=current display, 1=voltage display

void setup() {
  Serial.begin(250000);  // Start the serial communication
#ifdef DEBUG
  Serial.println("Setup...");
#endif
  Wire.begin();
  // Check if the LCD is connected
  Wire.beginTransmission(0x27);
  if (Wire.endTransmission() == 0) {
    // LCD is connected, proceed with initialization
    delay(50);
    lcd.begin(16, 2);
    lcd.backlight();
    lcd.clear();
  } else {
    // LCD is not connected, continue without initializing the LCD
#ifdef DEBUG
    Serial.println("Ei LCD:ta. Ohitus.");
#endif
  }
  // Change timers on pins to change PWM freq to 122 Hz
  // Pins D9 and D10 - 122 Hz
  TCCR1A = 0b00000001;  // 8bit
  TCCR1B = 0b00000100;  // x256 phase correct
  // Make pins output/input
  pinMode(currentPin, INPUT);       //Information on charging current
  pinMode(voltagePin, INPUT);       //information on voltage, for real use, delete _PULLUP
  pinMode(motorPin, INPUT_PULLUP);  //Vibration sensor in, for motor running detect,  for real use, delete _PULLUP (it is for test purpose, pullup resistor)
  pinMode(pwmPin, OUTPUT);          //Alternator pwm output
  pinMode(relayPin, OUTPUT);        //Ignition relay pin
  // Start Duty Cycle at 100 %, alternator electromagnet off, for starting the engine
  analogWrite(pwmPin, 255);
#ifdef DEBUG
  Serial.println("Setup ok.");
#endif
}

void motorRunning() {  //engine running function
  if (digitalRead(motorPin) == HIGH && motorStatus == 0) {
#ifdef DEBUG
    Serial.println("Kayntitieto...");
#endif
    if (!motorTime.started()) {  // Start the motorTime timer only, if it has not been started yet
      motorTime.start();         // Start the motorTime timer if it hasn't started yet
    }
    if (motorTime.done()) {  // Wait for motorTime to be done before moving to ramping up PWM
      motorStatus = 1;
#ifdef DEBUG
      Serial.println("Kaynnistetty.");
#endif
    }
  } else if (motorStatus == 0) {
    motorTime.stop();  // Stop the timer if motorPin is not high
#ifdef DEBUG
    Serial.println("Kaynnistys...");
#endif
    lcd.setCursor(0, 0);  //On lcd print Finnish to start the engine
    lcd.print("K");
    lcd.print((char)0xe1);
    lcd.print("ynnist");
    lcd.print((char)0xe1);
    lcd.print("   ");
    lcd.setCursor(0, 1);
    lcd.print("moottori");
  }
}

void rampUp() {  //rampup pwm
  // Ramp pwm up
  if (motorStatus == 1) {
    if (stepTime.repeat()) {
      analogWrite(pwmPin, pwmValues[currentPwmStep]);
      currentPwmStep++;
#ifdef DEBUG
      Serial.println("Ramp up...");
#endif
      if (currentPwmStep >= sizeof(pwmValues) / sizeof(pwmValues[0])) {  //checking the pwm step count
        motorStatus = 2;
      }
    }
  }
}

void shutDown() {  //engine shutdown, execute relay
  //If the charging current drops to 0 to 5 amperes and charging voltage drops under 14 volts and motor is running
  // start the shutdown function and turn off the relay
  if (current >= 0 && current < 5 && sensVoltage < 15 && digitalRead(motorPin) == HIGH && motorStatus == 2) {
    digitalWrite(relayPin, LOW);
    analogWrite(pwmPin, 15);  // Duty Cycle to 5 % before running down engine
    if (!shutTime.started()) {  //wait for shutDelay time to engine have time to stall down
      shutTime.start();
    }
    if (shutTime.done()) {
      analogWrite(pwmPin, 255);  // Stopped Duty Cycle at 100 %, alternator electromagnet off
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Sammutus");
      motorStatus = 3;  //motor has run, to reset, switch power off, on next startup, it will be reset
#ifdef DEBUG
      Serial.println("Sammutettu.");
#endif
    }
  } else if (motorStatus == 2) {
    motorTime.stop();              // Stop the timer if motor is in state 2 (normal running) not high
    digitalWrite(relayPin, HIGH);  //else, keep relay on and don't
#ifdef DEBUG
    Serial.println("Kaynnissa.");
#endif
  }
}

void showCurrent() {  //show current and voltage on lcd only when normal running state
  if (motorStatus == 2) {
    lcd.setCursor(0, 0);
    lcd.print("Virta:");
    lcd.setCursor(0, 1);
    lcd.print((float)current);
    lcd.print(" ");
    lcd.setCursor(5, 1);
    lcd.print(" A");
    lcd.setCursor(8, 0);
    lcd.print("J");
    lcd.print((char)0xe1);
    lcd.print("nnite:");
    lcd.setCursor(8, 1);
    lcd.print((float)sensVoltage);
    lcd.print(" ");
    lcd.setCursor(13, 1);
    lcd.print(" V");
#ifdef DEBUG
    Serial.println("Virta LCD.");
#endif
  }
}

void loop() {
  //calculate current from shunt reading
  // Calculate the charging current from the average and display it on the LCD screen.
  // take N readings and store them in the array
  for (int i = 0; i < N; i++) {
    readings[i] = analogRead(currentPin);
    delay(5);  // wait for 5 milliseconds between readings
  }
  // calculate the average of the N readings
  float sum = 0;
  for (int i = 0; i < N; i++) {
    sum += readings[i];
  }
  float average = sum / N;
  float voltage = average * voltageFactor;  //  Convert ADC reading to voltage

  current = (m * voltage + b) * currentCal;  // Convert voltage to current using the new linear equation

  //calculate high voltage from voltage divider input
  // Calculate the charging voltage from the average and display it on the LCD screen.
  // take Y readings and store them in the array
  for (int j = 0; j < Y; j++) {
    readingsV[j] = analogRead(voltagePin);
    delay(5);  // wait for 5 milliseconds between readings
  }
  // calculate the average of the N readings
  float sumV = 0;
  for (int j = 0; j < Y; j++) {
    sumV += readingsV[j];
  }
  float averageV = sumV / Y;
  float voltageV = averageV * voltageFactor;  //  Convert ADC reading to voltage
  sensVoltage = voltageV * sensVfactor;  // Convert voltage to real voltage

  motorRunning();
  rampUp();
  shutDown();
  showCurrent();
  Serial.print("Jannite: ");
  Serial.print((float)sensVoltage);
  Serial.println();
  Serial.print("Virta: ");
  Serial.print((float)current);
  Serial.println();
  Serial.print("Tila: ");
  Serial.print(motorStatus);
  Serial.println();
}
 
Viimeksi muokattu:
tota siis en itse käytä kyllä timer kirjastoja kun se onnistuu siis logiigalla jos sulla on esim rampup mitä ajetaan jossa nyt on delya(xxxX) niin mä teen esim long rampuptimer
sitten siellä void rampup
Koodi:
if(millis<millis()+1000)
{
#tää ajetaan silloin kun 1000ms eli sekunti onkulunut ja silloin se päivittää tuon rampuptimering.
rampuptimer = millis();
}
tossa vielä joku webppi sivu jossa tuota selostetaan.
 
No niin, eilisen ja tämän päivän aloin tuota koodia ähräämään ja löysin muutamankin ajastinkirjaston, kun en vieläkään tajua tuota millis() funktion käyttöä sen sijaan, että käyttäisi yksinkertaista, mutta muun toiminnan pysäyttävää delay() -funktiota. Löysin kirjastot BlockNot ja Neotimer, josta jälkimmäisen sain nähtävästi toimimaan tekoälykoodin avustuksella.

Joskus kirjastot on ihan ok. Se mikä noiden kanssa voi tulla aika nopeastikin vastaan on koodin koko, kirjastot kun tuppaa tekemään kaikenlaista mitä itse ei tarvitsisikaan. Tuo nyt ei vielä ole kovin iso mutta kannattaa pitää mielessä.
 
Joskus kirjastot on ihan ok. Se mikä noiden kanssa voi tulla aika nopeastikin vastaan on koodin koko, kirjastot kun tuppaa tekemään kaikenlaista mitä itse ei tarvitsisikaan. Tuo nyt ei vielä ole kovin iso mutta kannattaa pitää mielessä.
No, nykypäivänä jollakin arduinolla ei pitäisi ihan yhdellä tai kahdella kirjastolla tulla muisti sentään täyteen ellei oma koodi ole jo todella iso, toki osa kirjastoista on melkoista bloattia. Itse kyllä muistan kun joskus vuosia sitten tein olikohan se joku ATtiny tai vastaavan pienen kontrollerin kanssa projektia. Kontrollerissa tilaa oli olikohan 2 vai peräti 4 kilotavua, siinä sai jo välillä repiä kirjastoja riekaleiksi ja koittaa saada muutamia tavuja sieltä sun täältä säästettyä että koodi mahtui kontrolleriin. Ainakin HD44780-LCD:lle tein minimaalisen version josta oli kaikki turha poistettu, samoin DS18B20-onewire-kirjastolle tuli tehtyä vastaava "laihdutusleikkaus".
 
@Nasty76 , tuttu sivu! Lueskelin jo tuota aiemmin monta kertaa läpi, mutta ei vain mennyt kaaliin, miten tuo homma tapahtuu. :geek:

@ississ, joo tuossa katsoinkin tuota "Dynamic Memory" -kohtaa, jossa tuli tätä kirjastoa käyttäen 39 % käyttöön, ilman tätä jäi muistaakseni selvästi alle 30 prosenttiin.. Liekö käytönaikainen muistinkäyttö sitten vielä enempi? Parempihan se varmaan olisi käyttää mahdollisimman vähän kirjastoja, jolloin säästettäisiin resursseja. Kaipa se hidasteleva käyttökokemus monissa nykyvermeissä osin johtuu kirjastojen käytöstä. Ainakin varmaan yksi syy. Turhaa hommaa prosessorilla?

@Hyrava, kaikkea sitä pystyy tekemään, kun osaa! On nämä ohjelmointihommat mulle melkein täyttä hepreaa, monesti jokaisesta kirjaimesta tulee mieleen 10 kysymystä, eikä mistään löydä selkeää vastausta. Parempi olisi katsoa vaikka vuoden ajan päivittäin näitä hommia niin, että joku aina on neuvomassa oikeaan suuntaan, mutta ei nyt sellaisia ole lähipiirissä, eteenpäin on päästy varsinkin tämän ketjun vinkeillä. Koodia en osaa kirjoittaa paljon ollenkaan, mutta pianolla pystyn tekemään pari kolme biisiä päivässä. ;)

Tähän ketjuun on jo osallistunut uskomattoman auttavaisia henkilöitä, ja olen jo aikaisemminkin varmaan kiitellyt, mutta mitäpä suotta jarruttelemaan, niin kiitos nyt vaan taas. Homma etenee hitaasti, mutta välillä vakaasti!
 
Viimeksi muokattu:
Tosin kirjoitin näemmä ihan höpöhöpö esimerkin. piti oikeen ihmetellä arduino online emulaattorilla miten oon ton ite tehny joten tähän selkeä lukunen esimerkki miten noilla millis arvoilla voidaan tehdä non block ajoa.
Koodi:
int period = 1000; //Tämä on viive joka odotetaan
unsigned long ramptimer = 0; // tämä on muuttuja esim jos ajetaan ramppia ylös tms tämä esimerkki tulostaa kerran sekunnissa tuon hello n

 
void setup() {
    Serial.begin(115200);
}
 
void loop() {
    
  
  
   if(ramptimer + period  <millis())
   {
    ramptimer=millis();
       Serial.println("Hello");
    }
}
 
No, nykypäivänä jollakin arduinolla ei pitäisi ihan yhdellä tai kahdella kirjastolla tulla muisti sentään täyteen ellei oma koodi ole jo todella iso, toki osa kirjastoista on melkoista bloattia. Itse kyllä muistan kun joskus vuosia sitten tein olikohan se joku ATtiny tai vastaavan pienen kontrollerin kanssa projektia. Kontrollerissa tilaa oli olikohan 2 vai peräti 4 kilotavua, siinä sai jo välillä repiä kirjastoja riekaleiksi ja koittaa saada muutamia tavuja sieltä sun täältä säästettyä että koodi mahtui kontrolleriin. Ainakin HD44780-LCD:lle tein minimaalisen version josta oli kaikki turha poistettu, samoin DS18B20-onewire-kirjastolle tuli tehtyä vastaava "laihdutusleikkaus".

Joo, 44780 ja ds- koodia on myös puukotettu mahtumaan pienempiin piireihin.
Olen käyttänyt enemmän atmega48/88/168 ja attiny13/15/25 kuin noita isompia, siksi tulee helposti mietittyä ensin myös koon puolesta.

@Nasty76 , tuttu sivu! Lueskelin jo tuota aiemmin monta kertaa läpi, mutta ei vain mennyt kaaliin, miten tuo homma tapahtuu. :geek:

@ississ, joo tuossa katsoinkin tuota "Dynamic Memory" -kohtaa, jossa tuli tätä kirjastoa käyttäen 39 % käyttöön, ilman tätä jäi muistaakseni selvästi alle 30 prosenttiin.. Liekö käytönaikainen muistinkäyttö sitten vielä enempi? Parempihan se varmaan olisi käyttää mahdollisimman vähän kirjastoja, jolloin säästettäisiin resursseja. Kaipa se hidasteleva käyttökokemus monissa nykyvermeissä osin johtuu kirjastojen käytöstä. Ainakin varmaan yksi syy. Turhaa hommaa prosessorilla?

@Hyrava, kaikkea sitä pystyy tekemään, kun osaa! On nämä ohjelmointihommat mulle melkein täyttä hepreaa, monesti jokaisesta kirjaimesta tulee mieleen 10 kysymystä, eikä mistään löydä selkeää vastausta. Parempi olisi katsoa vaikka vuoden ajan päivittäin näitä hommia niin, että joku aina on neuvomassa oikeaan suuntaan, mutta ei nyt sellaisia ole lähipiirissä, eteenpäin on päästy varsinkin tämän ketjun vinkeillä. Koodia en osaa kirjoittaa paljon ollenkaan, mutta pianolla pystyn tekemään pari kolme biisiä päivässä. ;)

Tähän ketjuun on jo osallistunut uskomattoman auttavaisia henkilöitä, ja olen jo aikaisemminkin varmaan kiitellyt, mutta mitäpä suotta jarruttelemaan, niin kiitos nyt vaan taas. Homma etenee hitaasti, mutta välillä vakaasti!

Hidastelu riippuu kovasti siitä mitä kaikkea taustalla tehdään.
Hyvä esimerkki on arduino-framen digitalWrite(), jokaisella kutsukerralla se päättelee asioita annetun pinnin numeron perusteella (tämä tarvitaan että toimii kätevästi eri alustoilla), poistaa pwm:n käytöstä (= jos pinnille ei käytetä pwm:ää niin ei tarvitsisi), tallentaa avr- status- rekisterin ja poistaa keskeytykset käytöstä. Vasta sitten asetetaan lähtö ja palautetaan statusrekisteri ja keskeytykset.
Eli silloin kun tiedetään että joku pinni on vain digilähtö niin suurin osa tuosta on tavallaan turhaa ja voisi vaan kääntää portin oikeaan asentoon...

Ja kun aiemmin mainitsit koodin ymmärtämisestä siihen kuuluu yhtenä osana myös helppolukuisuus.
Kannattaa siis vaihtaa ne motorStatus = 2 -->> motorStatus = MOTOR_ON niin ei tarvitse muistaa mikä numero on mikä, antaa vaan jokaiselle numerolle selkeän tekstin.
Tiedoston alkuun vaan jonnekin #define MOTOR_ON 2 ja kaikki muut vastaavat myös, helpottaa lukemista huomattavasti eikä kuluta muistia yhtään koska kääntäjä käyttää suoraan noita numeroita.


Tosin kirjoitin näemmä ihan höpöhöpö esimerkin. piti oikeen ihmetellä arduino online emulaattorilla miten oon ton ite tehny joten tähän selkeä lukunen esimerkki miten noilla millis arvoilla voidaan tehdä non block ajoa.
Koodi:
int period = 1000; //Tämä on viive joka odotetaan
unsigned long ramptimer = 0; // tämä on muuttuja esim jos ajetaan ramppia ylös tms tämä esimerkki tulostaa kerran sekunnissa tuon hello n

 
void setup() {
    Serial.begin(115200);
}
 
void loop() {
   
 
 
   if(ramptimer + period  <millis())
   {
    ramptimer=millis();
       Serial.println("Hello");
    }
}

Ajan vertailu pitäisi tehdä (millis() - alkuaika) ja vertaamalla sitä rajaan, muuten tulee epämääräisiä aikoja kun millis vuotaa yli (n. 50 päivän välein). Eli mieluummin aina näin:
C++:
if ( ( millis() - ramptimer ) > period ) {
  ramptimer = millis();
  Serial.print("Hello");
}

Täältä lukemista jos kaipaa varmistusta: Arduino Tutorial: Avoiding the Overflow Issue When Using millis() and micros() – Norwegian Creations , How can I handle the millis() rollover?

Ja kyllä, jos oletetaan että systeemi ei koskaan ole ~50 päivää käytössä niin ei väliä. Mutta jos aina tekee samalla tavalla oikein niin sitten ei tarvitse miettiä miten pitää tehdä jos tarvitseekin pidempiä käyntiaikoja vaan menee heti oikein.
 

Uusimmat viestit

Statistiikka

Viestiketjuista
264 820
Viestejä
4 587 905
Jäsenet
75 494
Uusin jäsen
toke1

Hinta.fi

Back
Ylös Bottom