Arduino Polska Forum

Pełna wersja: Optymalizacja Kodu o 1% Arduino Uno
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Cześć.
Koledzy składam wagę z projektu który znalazłem i niestety na arduino uno zabrakło miejsca .
Nie jestem programistą i sam nie jestem w stanie kodu zoptymalizować. Jedynie usunąłem wybór języka i zaoszczędziłem 2%  pamięci. Jest jeszcze tylko o 1% za dużo więc ośmielam się prosić o pomoc tutaj na forum.

Cytat:Szkic używa 32856 bajtów (101%) pamięci programu. Maksimum to 32256 bajtów.


Cały projekt znajduje się tutaj https://www.thingiverse.com/thing:4131117
Kod do optyalizacji poniżej :
Kod:
/*      RADIN-LOADER
    by Blaise Lapierre (France)
    remixed by Daniel Mielke (Germany)

Serial Texts only english
LCD Text Multilanguage

I have added a lot of spelling mistakes, so have fun finding them.


   
PINOUT ARDUINO

[EN]  Arduino Pin on the device


0 /Arduino RX – not used
1 /Arduino TX – not used
2 HX711 – Dt
3 HX711 – Sck
5 Buzzer - Signal
10  DRV – Enable
11  DRV – Step
12  DRV – Dir

A0  Signal from 5 analog button plate
A4  SDA LCD i2c
A5  SCL LCD i2c

ARef  VCC buttons (VCC boutons)
5V    DRV8825 Rst+Slp+M0+M1 //fix 1/8 Steps
3,3V  HX711 - Vcc
5V    LCD i2c – Vcc
5V    Buzzer Vcc
Gnd   LCD i2c – Gnd
Gnd   HX711 Gnd / Buttons Gnd  / DRV8825 Gnd /Buzzer Gnd

+ Capacitor  >12V 100u / DRV Vmot
- Capacitor  >12V 100u / DRV Gnd (mot)
*/

//LIBRARIES INCLUDED IN THE PROGRAM
#include <Wire.h>
#include <EEPROM.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include <AccelStepper.h>
#include <HX711.h>
#include <avr/pgmspace.h>

//I2C for LCD
hd44780_I2Cexp lcd;



//fix values Const and Defines

//Define PinOut
 
  //Buzzer defines
  #define BUZZsig 5

  // Stepper constant
  #define drvdirPin 12            // Direction Pin of the driver, needed for the Libary. We use only one direction
  #define drvstepPin 11           // Impulsion pin of the driver, 1pulse=1step
  #define drvenPin 10             // Driver activation Pin, 0V=enable

  //Scale defines
   #define s1dtPin 2
   #define s1sckPin 3

// Memory
  const int address_startramp = 0;  // Addess for Memory, that stores: float startramp
  const int address_endramp = 10;  // Stores float endramp
  const int address_maxspeed = 20;  // Stores float minspeed
  const int address_minspeed = 30;  // Stores float maxspeed
  const int address_tolerance = 40;  // Stores float tolerance
  const int address_autotara = 50;  // Stores bool autotara
  const int address_Language = 53;  // Stores byte LAnguage
  const int address_scaleunit = 56;  // Stores bool  scaleunit
  const int address_SW1 = 60;       // Stores int(2byte) SW1
  const int address_SW2 = 63;       // Stores int SW2
  const int address_SW3 = 66;     // Stores int SW3
  const int address_SW4 = 69;     // Stores int SW4
  const int address_SW5 = 72;     // Stores tnt SW5
  const int address_ScaleOffset = 80;  // Stores long ScaleOffset
  const int address_ScaleFactor = 90;  // Stores float ScaleFactor
  const int address_memory[]= {100,110,120,130,140}; //Memoryadresses.. watch how many needed
  const byte memspace = 5; //How many Memorys ? don't forget to give memory adresses!

//Menu
  const byte numberofentrys =12;

//Gramm/Grain
  const float gr_gn= 15.432358; // Faktor to change gramm to grain
  const byte avarage_number =7; //amount of Data to build an Average
 
  //Switches
  const int noSWpressed = 900;//value returned to A0 superior to this when no button is pressed (0 - 1023)
  const byte swtolerance = 10; //tolerance of tension read on A0 around the switch value (0 - 1023)

  //beeps
  const byte right_dose = 1;
  const byte overdose_dose = 2;
  const byte failed_dose = 3;
  const int beep_time =500 ;

  //
  const unsigned long timeout=90000;

  //LCD texts in English
  const char str_startline1_en[] PROGMEM = " RADIN LOADER";   // maximum 16 sign !
  const char str_startline2_en[] PROGMEM = " starting...";    // maximum 16 sign !
  const char str_swcalib_en[] PROGMEM = "switch calibrate";   // maximum 15 sign !
  const char str_pressSW_en[] PROGMEM = "press switch";       // maximum 14 sign !
  const char str_memsave_en[] PROGMEM = "data saved";         // maximum 16 sign !
  const char str_scalecalib_en[] PROGMEM = "scale calibrate"; // maximum 16 sign !
  const char str_scaleempty_en[] PROGMEM = "empty Scale!";   // maximum 16 sign !
  const char str_scaleentcaliweigth_en[] PROGMEM = "Cal.Weig.";    // maximum 8 sign !
  const char str_overdosed_en[] PROGMEM = "overdosed";   // maximum 16 sign !
  const char str_dosedone_en[] PROGMEM = "dosing finished";       // maximum 16 sign !
  const char str_timeout_en[] PROGMEM = "stopp or timeout";         // maximum 16 sign !
  const char str_ask_en[] PROGMEM = "are you sure?"; // maximum 15 sign !
  const char str_memory_en[] PROGMEM = "Memory"; // maximum 14 sign !
  const char str_on_en[] PROGMEM = "on"; // maximum 15 sign !
  const char str_off_en[] PROGMEM = "off"; // maximum 15 sign !
  const char str_english_en[] PROGMEM = "english"; // maximum 15 sign !
  const char str_2ndlanguage_en[] PROGMEM = "german"; // maximum 15 sign !
  const char str_3ndlanguage_en[] PROGMEM = "french"; // maximum 15 sign !

  // LCD Texts second Language (deutsch)
  const char str_startline1_2d[] PROGMEM = " RADIN LOADER ";  // maximum 16 sign !
  const char str_startline2_2d[] PROGMEM = " startet..";      // maximum 16 sign !
  const char str_swcalib_2d[] PROGMEM = "Taster Kalib.";      // maximum 15 sign !
  const char str_pressSW_2d[] PROGMEM = "druecke Taster";      // maximum 14 sign !
  const char str_memsave_2d[] PROGMEM = "Daten gesichert";    // maximum 16 sign !
  const char str_scalecalib_2d[] PROGMEM = "Waage kalib.";    // maximum 16 sign !
  const char str_scaleempty_2d[] PROGMEM = "Waage leeren!";  // maximum 16 sign !
  const char str_scaleentcaliweigth_2d[] PROGMEM = "Kal.Gew.";      // maximum 8 sign !
  const char str_overdosed_2d[] PROGMEM = "Ueberdosiert";      // maximum 16 sign !
  const char str_dosedone_2d[] PROGMEM = "Dosieren Ende";      // maximum 16 sign !
  const char str_timeout_2d[] PROGMEM = "Stop oder Zeitum";    // maximum 16 sign !
  const char str_ask_2d[] PROGMEM = "sicher ?";    // maximum 15 sign !
  const char str_memory_2d[] PROGMEM = "Speicher";    // maximum 15 sign !
  const char str_on_2d[] PROGMEM = "EIN";    // maximum 15 sign !
  const char str_off_2d[] PROGMEM = "AUS";    // maximum 15 sign !
  const char str_english_2d[] PROGMEM = "englisch";    // maximum 15 sign !
  const char str_2ndlanguage_2d[] PROGMEM = "deutsch";    // maximum 15 sign !
  const char str_3ndlanguage_2d[] PROGMEM = "franzoes.";    // maximum 15 sign !

  // LCD Texts third Language (french)
  const char str_startline1_3d[] PROGMEM = " RADIN LOADER ";  // maximum 16 sign !
  const char str_startline2_3d[] PROGMEM = " Demarrage...";      // maximum 16 sign !
  const char str_swcalib_3d[] PROGMEM = "Calib. boutons";      // maximum 15 sign !
  const char str_pressSW_3d[] PROGMEM = "App. /boutons";      // maximum 14 sign !
  const char str_memsave_3d[] PROGMEM = "sauvegarde";    // maximum 16 sign !
  const char str_scalecalib_3d[] PROGMEM = "Calib. pesee";    // maximum 16 sign !
  const char str_scaleempty_3d[] PROGMEM = "Balance vide!";  // maximum 16 sign !
  const char str_scaleentcaliweigth_3d[] PROGMEM = "CalPoids";      // maximum 8 sign !
  const char str_overdosed_3d[] PROGMEM = "Surcharge";      // maximum 16 sign !
  const char str_dosedone_3d[] PROGMEM = "Dose OK";      // maximum 16 sign !
  const char str_timeout_3d[] PROGMEM = "Erreur";    // maximum 16 sign !
  const char str_ask_3d[] PROGMEM = "etes vous sur?";    // maximum 15 sign !
  const char str_memory_3d[] PROGMEM = "Memoire";    // maximum 15 sign !
  const char str_on_3d[] PROGMEM = "on";    // maximum 15 sign !
  const char str_off_3d[] PROGMEM = "off";    // maximum 15 sign !
  const char str_english_3d[] PROGMEM = "english";    // maximum 15 sign !
  const char str_2ndlanguage_3d[] PROGMEM = "allemand";    // maximum 15 sign !
  const char str_3ndlanguage_3d[] PROGMEM = "francais";    // maximum 15 sign !

  const byte number_languages = 3 ;//how many languages do we have ?
 
// Cobines Texts to String Array ( 2D Array)
  const char *const str_startline1[] PROGMEM = {str_startline1_en, str_startline1_2d, str_startline1_3d};
  const char *const str_startline2[] PROGMEM = {str_startline2_en, str_startline2_2d, str_startline2_3d};
  const char *const str_swcalib[] PROGMEM = {str_swcalib_en, str_swcalib_2d, str_swcalib_3d};
  const char *const str_pressSW[] PROGMEM = {str_pressSW_en, str_pressSW_2d, str_pressSW_3d};
  const char *const str_memsave[] PROGMEM = {str_memsave_en, str_memsave_2d, str_memsave_3d};
  const char *const str_scalecalib[] PROGMEM = {str_scalecalib_en, str_scalecalib_2d, str_scalecalib_3d};
  const char *const str_scaleempty[] PROGMEM = {str_scaleempty_en, str_scaleempty_2d, str_scaleempty_3d};
  const char *const str_scaleentcaliweigth[] PROGMEM = {str_scaleentcaliweigth_en, str_scaleentcaliweigth_2d, str_scaleentcaliweigth_3d};
  const char *const str_overdosed[] PROGMEM = {str_overdosed_en, str_overdosed_2d, str_overdosed_3d};
  const char *const str_dosedone[] PROGMEM = {str_dosedone_en, str_dosedone_2d, str_dosedone_3d};
  const char *const str_timeout[] PROGMEM = {str_timeout_en, str_timeout_2d, str_timeout_3d};
  const char *const str_ask[] PROGMEM = {str_ask_en, str_ask_2d, str_ask_3d};
  const char *const str_memory[] PROGMEM = {str_memory_en, str_memory_2d, str_memory_3d};
  const char *const str_on[] PROGMEM = {str_on_en, str_on_2d, str_on_3d};
  const char *const str_off[] PROGMEM = {str_off_en, str_off_2d, str_off_3d};
  const char *const str_english[] PROGMEM = {str_english_en, str_english_2d, str_english_3d};
  const char *const str_2ndlanguage[] PROGMEM = {str_2ndlanguage_en,str_2ndlanguage_2d,str_2ndlanguage_3d};
  const char *const str_3ndlanguage[] PROGMEM = {str_3ndlanguage_en,str_3ndlanguage_2d,str_3ndlanguage_3d};

  const String str_Setpoint[]=                     {"setpoint","Sollwert","Cible"}; //maximun 8 sign
  const String str_actweigth[]=                    {"actual","Istwert","Actuel"}; //maximun 8 sign


//Variables (Global)

  // Buttons variables (Variables boutons)
  int SW1; //value returned by button SW1
  int SW2; //value returned by button SW2
  int SW3; //value returned by button SW3
  int SW4; //value returned by button SW4
  int SW5; //value returned by button SW5
  bool SWcalib; //button calibration is required
  byte SWnumber;  //button number for advices
  int a0value;    //Temp Storage for analoge value

  //scale variables
  float W_Setpoint ;// The Setpoint @Startup, not in Memory! to much memora traffic evey time it changes to store it
  float W_actual;   //the actual weight from scale, temp used to build average
  long  ScaleOffset;   // digits from scale for tara (digits wihout load)
  float ScaleFactor;   //factor to convert digits tu unit(g or gn)
  byte scalecalib; // step in scalecalibration
  float scalecalibweight =10.00; // Enter the weight here you usually use to calibrate the scale
  float average[avarage_number]; // build an avarage of weight in the mainloop

  //Dosing variables
  float startramp ; // value before Setpoint, ramp dosing will be started
  float endramp ;   //value before Setpoint, slow dosing will be started
  float maxspeed ; //Speed while fast dosing
  float minspeed ; // Speed while slow dosing
  float tolerance ; // tolerance to check if dosing was fine
  bool dosedone;  // Bit for Dosing finished
  bool overdose; // Bit for Overdosed
 
  //temp Variables
  unsigned int timer; // time in ms for value acceleration will be reduced every loop while button hold
  char PufferChar[17]; //Buffer for LCD +1 Emergency Char
  unsigned long lastmillis; //Timer for Dosing every 110ms a weight will be read from HX711
  unsigned long dosestart; // Time when dosing has been started for Timeout
  byte show_dec; //amount of decimals while showing Values (2 for gn, 3 for gr)


  //Parameters
  byte Language ; // Set this value to set the language 0= eng, 1=german, 2=french
  int new_Language ; // Menu the new Language that could be choosen
  bool scaleunit ; //0=gramm , 1=grain
  bool autotara ; // Parameter in Menu, tara @ dosing start
 

  //menu variables
  bool menuon; //Menu is on, hold while loops
  bool submenuon; // entered submenu for while loops
  bool menuupdate; // new parameters to show on display(main menu)
  bool updatememory; // something new to write in Memory
  int  menuentry ; //where are we in menu
  bool submenuupdate; // new parameters to show on display(submenu)

  //memory var
  int memlocation; //needed in Menu to know which location to  load/save
 
 
   //Menu Text
   String menu[numberofentrys]; //a String holding the textes for the menu


  //Stepper Motor will be known as stepper
  AccelStepper stepper(1, drvstepPin, drvdirPin); // "stepper" (driver, pin step, pin direction)
 
  //LoadModul on HX711 will be known as scale
  HX711 scale; //Connect weighing inputs on pin

void setup() {
  // put your setup code here, to run once:

  //start LCD Display
  lcd.begin(16, 2); //declare LCD 16 chars and 2 rows and start it
 
  //Start Serial Port, Debug and more Information
  Serial.begin(19200); //Serial initialisation
  Serial.println(F("Starting RADIN_LOADER")); // print text to serial

  //Read needed Eeprom Data
  EEPROM.get(address_SW1, SW1);
  EEPROM.get(address_SW2, SW2);
  EEPROM.get(address_SW3, SW3);
  EEPROM.get(address_SW4, SW4);
  EEPROM.get(address_SW5, SW5);
  EEPROM.get(address_ScaleOffset, ScaleOffset);
  EEPROM.get(address_ScaleFactor, ScaleFactor);
  EEPROM.get(address_startramp, startramp);
  EEPROM.get(address_endramp, endramp);
  EEPROM.get(address_maxspeed, maxspeed);
  EEPROM.get(address_minspeed, minspeed);
  EEPROM.get(address_tolerance, tolerance);
  EEPROM.get(address_autotara, autotara);
  EEPROM.get(address_Language, Language);
  EEPROM.get(address_scaleunit, scaleunit);
  EEPROM.get(address_memory[0], W_Setpoint); //Gets Memory 1 to set Setpoint @ Startup
  Serial.println(F("Memory loaded")); // print text to serial

  //load defaults if 0 in case you had the first run or not changed parameters yet
  if (maxspeed==0){maxspeed=800;}
  if (minspeed==0){minspeed=100;}
  if (startramp==0){startramp=0.3;}
  if (endramp==0){endramp=0.1;}

 
  //get texts in language
  language(); // Load the Texts for the Menus in the right language
  Serial.println(F("Language loaded")); // print text to serial
 
  //Show Start LCD
  lcd.clear(); // clear LCD  for new textes
  lcd.setCursor(0,0); //move LCD Cursor to Start Text from there
  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_startline1[Language])));  // Load the Text from Progmem in right language to Buffer
  lcd.print(PufferChar); // Print Buffer
  lcd.setCursor(0,1);
  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_startline2[Language])));
  lcd.print(PufferChar);

  //Init AnalogIn
  pinMode(A0, INPUT); // PINMode A0 = analoge Input
  Serial.print(F("Init Analog In0 First Value: ")) && Serial.println(analogRead(A0)); // Serial Text
  //The analoge Input should be read in Setup first time, because the first value is always crap.
  //If you don't do an go in switch calibration wrong values will be stored
 
  //Init Buzzer
  pinMode(BUZZsig, OUTPUT); // Pin for Buzzer = Output
  Serial.println(F("Init Buzzer done"));
 
  //stepper setup
  pinMode(drvenPin, OUTPUT); //Pin= Output, other Pins are handled in Libary
  digitalWrite(drvenPin, HIGH); // High=disable driver
  stepper.setMaxSpeed(10000); // Maximum pulse rate to the driver, depends on magnetfields of motor
  Serial.println(F("Init Stepper done"));
 
  //Scale beginn & Check
  scale.begin(s1dtPin, s1sckPin); //start h711
  Serial.println(F("InitScale done"));
  delay(100);
  //check if scale is ready(doesn't work very well)
  if (scale.is_ready())//check if scale is ready(doesn't work very well)
  {
  Serial.println(F("Scale is Ready"));
  }
  else
  {
  Serial.println(F("Scale error!!"));
  }

  //Check if Switch Calibration Required (Memory is empty or switch values are equal?)
  /*//Serial.print(F("SW1 Value: ")) && //Serial.println(SW1);
  //Serial.print(F("SW2 Value: ")) && //Serial.println(SW2);
  //Serial.print(F("SW3 Value: ")) && //Serial.println(SW3);
  //Serial.print(F("SW4 Value: ")) && //Serial.println(SW4);
  //Serial.print(F("SW5 Value: ")) && //Serial.println(SW5);
  */
  if(SW1 < 0 || SW1 > 1023 || SW1 == SW2 || SW1 == SW3 || SW1 == SW4|| SW1 == SW5)
    {SWcalib = true;}
  if(SW2 < 0 || SW2 > 1023 || SW2 == SW3 || SW2 == SW4|| SW2 == SW5)
    {SWcalib = true;}
  if(SW3 < 0 || SW3 > 1023 || SW3 == SW4|| SW3== SW5)
    {SWcalib = true;}
  if(SW4 < 0 || SW4 > 1023  || SW4 == SW5)
    {SWcalib = true;}
  if(SW5 < 0 || SW5 > 1023)
    {SWcalib = true;}
   
  if(SWcalib) //calibration required
  {
    Serial.println(F("Scwitches need calibration"));
    swcalibration();
  }
  else //values for switches are fine
  {
    Serial.println(F("Switch Memory okay"));
  }

  //Check if Memorydata for Scale exist
  if(ScaleOffset == 0 || ScaleFactor == 0) // No Data = calibration
  {
    Serial.println(F("Scale needs calibration"));
    scalecalibration();
  }
  else // Data found, then load it from Memory to HX711
  {
    scale.set_offset(ScaleOffset); //Load Offset
    scale.set_scale(ScaleFactor); // Load ScaleFactor ( makes digits to Unit)
    Serial.println(F("Scale Memory loaded"));
  }

  delay(1000); // Hold Starting Display a moment
  lcd.clear();
  Serial.println(F("Setup finished"));

  ///END of SETUP !!!!!
}



void loop() {
//Main Routine showing Scale Value and wait for buttons to do something


  // Build an scale average, we need that for smoothing the scale
  W_actual=0; // delete the last actual value
  for(int i= avarage_number-1;i>0;i--) //shift the last values
  {
  average[i]= average[i-1];
  W_actual+=average[i]; //add all data to actual value
  }
  average[0]=scale.get_units(1);//get one value from hx711 (not more !, it takes to much time, we could miss a pressed button)
  W_actual+=average[0];//add it to value
  W_actual=W_actual/avarage_number; // divide now to have an average

  // Put Texts on Display
  lcd.setCursor(0,0);
  lcd.print(str_Setpoint[Language]);
  lcd.setCursor(0,1);
  lcd.print(str_actweigth[Language]);
  //Put weight values on LCD
  lcd_print_weight(W_actual,8,1); //actual weight& unit to LCD
  lcd_print_weight(W_Setpoint,8,0); //Put Setpoint & unit to LCD

  //check if a button is pressed
  if(analogRead(A0) < noSWpressed) // a button is pressed
  {
   delay(10); // wait a short time, to prevent keybounce
    a0value= analogRead(A0); //read value now again
    if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance) // button 5 is pressed
        {
        dose();   //start a dosing process
        }
    if(a0value >= SW4-swtolerance && a0value <= SW4+swtolerance) // button 4 is pressed
        {
        scale.tare(5);  // tara scale with 5 values
        Serial.println(F("Scale Tara"));  
        }
    if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance) // button 3 is pressed
        {
        W_Setpoint= weight_change_acc(SW3,W_Setpoint, -0.01,-0.01, 8, 0); // we lower the Setpoint, hold it go fast
        Serial.print(F("new Setpoint"));
        Serial.println(W_Setpoint);
        }
    if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)// button 2 is pressed
        {
         W_Setpoint= weight_change_acc(SW2,W_Setpoint, 0.01,0.01, 8, 0);  // we increase the Setpoint, hold it go fast
         Serial.print(F("new Setpoint"));
         Serial.println(W_Setpoint);
        }
    if(a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)// button 1 is pressed
        {
         mymenu();  //we go into the menu
        
        }
}    

//Main Routine End             
}






void language()
//here we load the Menu textes in the language that is used (textes in RAM)
{
  //all Menu Texts 15 Sign max
  if(Language == 0){ //if english ######################################

  menu[0]="memory load";
  menu[1]="memory save";
  menu[2]="calibrate scale";
  menu[3]="unit";
  menu[4]="autotara";
  menu[5]="dose speed fast";
  menu[6]="dose speed slow";
  menu[7]="ramp start";
  menu[8]="ramp end";
  menu[9]="tolerance";
  menu[11]="factory reset";

  }//end if language = 0 ##########################################

}


void swcalibration()
// calibrate the switches ( after factory reset or first run ever)
//  analogvalues will be checked, an sorted to the buttons
{

  Serial.println(F("switch calibration started"));
  Serial.print(F("NoSwitch =")) && Serial.println(analogRead(A0)); // Read the Value when no switch is pressed
  SWnumber = 1; // Set the first switch to be calibrated

  //write Text to LCD, ask for the first switch to be pressed by user
  lcd.clear();
  lcd.setCursor(0,0);
  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_swcalib[Language])));
  lcd.print(PufferChar);
  lcd.setCursor(0,1);
  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_pressSW[Language])));
  lcd.print(PufferChar);
  lcd.setCursor(15,1);
  lcd.print(SWnumber);

  //While Loop, stay here until all 5 buttons are finished.
  while(SWcalib == true)
  {
  if(analogRead(A0) < noSWpressed) //a button is pressed
    {
    delay(50); // make sue bounce protection
    a0value= analogRead(A0); //read again ! In moment pressed a wrong value possible (bounce)
    Serial.println(F("Button pressed"));
    //clear second Line and writa data saved
    lcd.setCursor(0,1);
    lcd.print(F("                ")); //clear only line 1
    lcd.setCursor(0,1);
    strcpy_P(PufferChar, (char *)pgm_read_word(&(str_memsave[Language])));
    lcd.print(PufferChar);
    //check where we are and save value to the button
     if(SWnumber == 1) // we are @Button 1
     {
        SW1 = a0value ; //set value to variable
        EEPROM.put(address_SW1, SW1); // save it to memory
        Serial.print(F("Saved SW1 = ")) && Serial.println(a0value);
      }//end if

      if(SWnumber == 2)// we are @Button 2
      {
        SW2 = a0value;//set value to variable
        EEPROM.put(address_SW2, SW2);// save it to memory
        Serial.print(F("Saved SW2= ")) && Serial.println(a0value);
      }//end if

      if(SWnumber == 3)// we are @Button 3
      {
        SW3 = a0value;//set value to variable
        EEPROM.put(address_SW3, SW3);// save it to memory
        Serial.print(F("Saved SW3= ")) && Serial.println(a0value);
      }//end if
     
      if(SWnumber == 4)// we are @Button 4
      {
        SW4 = a0value;//set value to variable
        EEPROM.put(address_SW4, SW4);// save it to memory
        Serial.print(F("Saved SW4= ")) && Serial.println(a0value);
      }//end if

      if(SWnumber == 5)// we are @Button 5
      {
        SW5 = a0value;//set value to variable
        EEPROM.put(address_SW5, SW5);// save it to memory
        Serial.print(F("Saved SW5= ")) && Serial.println(a0value);      
      }//end if
    SWnumber++; //next button now :-)
    delay(4000); // time to release button and show "memory saved"
    //show the next button on LCD to calibrate
    lcd.clear();
    lcd.setCursor(0,0);
    strcpy_P(PufferChar, (char *)pgm_read_word(&(str_swcalib[Language])));
    lcd.print(PufferChar);
    lcd.setCursor(0,1);
    strcpy_P(PufferChar, (char *)pgm_read_word(&(str_pressSW[Language])));
    lcd.print(PufferChar);
    lcd.setCursor(15,1);
    lcd.print(SWnumber);
  }
 
  if(SWnumber >= 6) // all five buttons are calibrated time to leave calibration
  {
    Serial.println(F("End Switch Calibration"));
    SWcalib = false; // finished, leave while loop
    lcd.clear();
  }
}
}

void scalecalibration()
{
  //calibrate scale, zero point and second point by weight

  //LCD texts for starting calibration
  lcd.clear();
  lcd.setCursor(0,0);
  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_scalecalib[Language])));
  lcd.print(PufferChar);
  Serial.println(F("scale calibration started"));
  delay(1000); //Show text for 1Sek
  scalecalib=1; //starting calibration with step 1
  while (scalecalib != 0) //stay into loop until calibration finished
  {
      switch (scalecalib)
      {
      case 1://step 1 show text for zeropoint calibration
        lcd.clear();
        lcd.setCursor(0,0);
        strcpy_P(PufferChar, (char *)pgm_read_word(&(str_scaleempty[Language])));
        lcd.print(PufferChar);
        delay(500);// after Scale is empty wait to get a few scale values to Offset
        lcd.setCursor(0,1);
        strcpy_P(PufferChar, (char *)pgm_read_word(&(str_pressSW[Language])));
        lcd.print(PufferChar);
        lcd.setCursor(15,1);
        lcd.print(F("5"));
        scalecalib=2; //next step
        break;
       
      case 2: //step 2 wait for switch 5 to do a zeropoint calibration
        a0value= analogRead(A0); //analog read to find if button is pressed
        if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)//button 5 is pressed
        {
          ScaleOffset=scale.read_average(10); // get digts from loop (average of 10 )
          EEPROM.put(address_ScaleOffset, ScaleOffset); // put as tara to memory
          scale.set_offset(ScaleOffset); //load to hx711 for tara
          Serial.println(F("scale offset calibrated"));
          Serial.print(F("Scale Offset= ")) && Serial.println(ScaleOffset);
          //lcd print memory is saved
          lcd.clear();
          lcd.setCursor(0,1);
          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_memsave[Language])));
          lcd.print(PufferChar);
          delay(2000);// show text for a short time
          //print LCD texts for calibration with calibration weight
          lcd.clear();
          lcd.setCursor(0,0);
          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_scaleentcaliweigth[Language])));
          lcd.print(PufferChar);
          lcd.setCursor(15,0);
          lcd.print(F("g"));
          lcd.setCursor(0,1);
          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_pressSW[Language])));
          lcd.print(PufferChar);
          lcd.setCursor(15,1);
          lcd.print(F("5"));
          scalecalib=3; //next step
        }
        break;
      
      case 3: // step calibrate the entered weight
       lcd_print_weight(scalecalibweight,8, 0); // print the actual calibration weight
       a0value= analogRead(A0); // read analog for buttons
       delay(50);// delay for button bouncing
       if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance) // button 2 is pressed incre<ase calibration weight
       {
        scalecalibweight= weight_change_acc(SW2,scalecalibweight, 0.001 , 0.001, 8, 0);
      
       }
       if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance) // button 3 is pressed lower calibration weight
       {
        scalecalibweight= weight_change_acc(SW3,scalecalibweight, -0.001, -0.001, 8, 0);
          
       }
       if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)//button 5 calibrate scale with calibration weight 
       {
        ScaleFactor= ((float)scale.read_average(10)-(float)ScaleOffset)/scalecalibweight; // math find scalefactor for g
        if(scaleunit == 1 ) //actual unit is gn
        {
        ScaleFactor= ScaleFactor/gr_gn; //change scalefactor to gn
        }
        EEPROM.put(address_ScaleFactor, ScaleFactor); //write scale factor to memory
        scale.set_scale(ScaleFactor); //set scale factor to hx711
        // some info to Serial
        Serial.print(F("Scale Calibtraion weigth = ")) && Serial.println(scalecalibweight);
        Serial.print(F("Scale Calibtraion raw weigth = ")) && Serial.println(scale.read_average(10));
        Serial.print(F("Scale Calibtraion factor = ")) && Serial.println(ScaleFactor);
        lcd.clear();
        scalecalib=0; //Exit Calibration !! 
        
       }
        break;
      default:
       // if nothing else matches, do the default
       // default is optional
        break;
      }
    }
  }


float weight_change_acc(int button, float value, float add_g,float add_gn, byte lcd_cursor, byte lcd_line)
// A function to Adjust weight values and show them on disply, hold but to accelerate value change
{
  //direction by negative add values
    timer =200;
    while(a0value >= button-swtolerance && a0value <= button+swtolerance) // the buttons is pressed
    {
     
     
      timer=timer/1.1f; // reduce timer by every loop the button is pressed
      if(scaleunit==0) // g is unit
      {
      value=value+add_g; // add the value for g
      }
      else //gn is unit
      {
      value=value+add_gn; //add the value for gn
      }
      lcd_print_weight(value,lcd_cursor,lcd_line); //print the atual weight you are changing  on LCD
      delay(timer); // time to wait for next loop
      a0value=analogRead(A0);
    }
    return value;
}

float speed_change_acc(int button, float value, float add, byte lcd_cursor, byte lcd_line)
{
  // A function to Adjust a  not weight value and show it on disply, hold but to accelerate value change
  //direction by negative add values
    timer =200;
    while(a0value >= button-swtolerance && a0value <= button+swtolerance) // the buttons is pressed
    {

      timer=timer/1.1f; // reduce timer by every loop the button is pressed
      value=value+add; // add the value
      lcd.setCursor(lcd_cursor,lcd_line);//print the atual value you are changing  on LCD
      lcd.print(value);
      delay(timer);// time to wait for next loop
      a0value=analogRead(A0);
    }
    return value;
}

void dose()
//dosing process is started
{
  //print LCD infos
  Serial.println(F("dosing started"));
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(str_Setpoint[Language]);
  lcd.setCursor(0,1);
  lcd.print(str_actweigth[Language]);
  lcd_print_weight(W_actual,8,1);
  lcd_print_weight(W_Setpoint,8,0);
 
  digitalWrite(drvenPin, LOW); //enable stepper
  if(autotara==1) // autotara is choosen
  {
  scale.tare(7);  //tara scale
  }
  dosestart=millis(); //remember the moment dosing is started for timeout
  dosedone=0; //dosing not done yet
  overdose=0; // not overdosed yet
  a0value=analogRead(0); // read analog value to make sure there is no old value
  while(dosedone == 0 && (millis() - dosestart < timeout)&&((a0value > SW4+swtolerance) || (a0value < SW4-swtolerance)))//Dose until finished or Timeout or sw4 is pressed
    {
    a0value=analogRead(0); // check if button is pressed
    W_actual=scale.get_units(7);//get Units from Scale high precision
   
    if (W_Setpoint <= (W_actual+tolerance) && W_Setpoint >= (W_actual-tolerance)) // dosing in in Tolerancelimit --- finished
    {
      dosedone=1; // dosing finished
    }
    if ((W_actual-W_Setpoint) > tolerance) // dosing over tolerance limit
    {
      overdose=1; // dosing done
      dosedone=1; // but overdosed
    }
   
    lcd_print_weight(W_actual,8,1); // put dosed value on lcd
    if((W_Setpoint-W_actual) >= startramp) //starting fast dosing
      {
      Serial.println(F("fast"));
      stepper.setSpeed(maxspeed*8);//max speed and 1/8 steps
      while((W_Setpoint-W_actual >= startramp )&& (millis() - dosestart < timeout)&&((a0value > SW4+swtolerance) || (a0value < SW4-swtolerance))) //stay in fast dosing
        {
          lastmillis=millis();//start tickling time
          while((millis() - lastmillis < 110)&& (millis() - dosestart < timeout)) //dose and every 110ms sclae weight
            {
              stepper.runSpeed();  // turn the stepper motor
            }
           W_actual=scale.get_units(1);//get one Unit from Scale
           lcd_print_weight(W_actual,8,1); // show weight on display
           a0value=analogRead(0);
        }
     
      }

    if(((W_Setpoint-W_actual) >= endramp)&& ((W_Setpoint-W_actual) < startramp)) //starting ramp dosing
      {
      Serial.println(F("ramp"));
      while((W_Setpoint-W_actual >= endramp )&& (millis() - dosestart < timeout)&&((a0value > SW4+swtolerance) || (a0value < SW4-swtolerance))) //stay in ramp dosing
        {
          stepper.setSpeed(8*((maxspeed-minspeed)/(startramp-endramp))*(W_Setpoint-W_actual-endramp)); // 1/8steps =x8 build a linear ramp
          lastmillis=millis();//start tickling time
          while((millis() - lastmillis < 110)&& (millis() - dosestart < timeout)) //&& a0value > SW4+swtolerance && a0value < SW4-swtolerance   dose and every 110ms sclae weight
            {
            stepper.runSpeed();  // turn the steppermotor
            }
           W_actual=scale.get_units(2);//get Units from Scale
           lcd_print_weight(W_actual,8,1);
           a0value=analogRead(0);
        }
     
      }
      if(((W_Setpoint-W_actual) >= 0)&& ((W_Setpoint-W_actual) < endramp)) //starting slow dosing
      {
      Serial.println(F("slow"));
      stepper.setSpeed(minspeed); // min speed
      while((W_Setpoint-W_actual >= 0 )&& (millis() - dosestart < timeout)&&((a0value > SW4+swtolerance) || (a0value < SW4-swtolerance))) //stay in ramp dosing
        {
          stepper.setSpeed(minspeed); // min speed
          lastmillis=millis();//start tickling time
          while((millis() - lastmillis < 110)&& (millis() - dosestart < timeout)) //dose and every 110ms sclae weight
            {
            stepper.runSpeed(); 
            }
           W_actual=scale.get_units(4);//get Units from Scale
           lcd_print_weight(W_actual,8,1);
           a0value=analogRead(0);
        }
     
      }
 
 
 
  //end
    }//big while Ends
  digitalWrite(drvenPin, HIGH); // High=disable driver
  lcd.clear();
  if(overdose==1) // dosing finished overdosed
  {
   Serial.println(F("Overdosed"));
   lcd.setCursor(0,0);
   strcpy_P(PufferChar, (char *)pgm_read_word(&(str_overdosed[Language])));
   lcd.print(PufferChar);
   lcd_print_weight(W_actual,8,1);
   for(int i= 0;i<=(2*overdose_dose)-1;i++) //Beeps for overdose
      {
       digitalWrite(BUZZsig, !digitalRead(BUZZsig)); 
       delay(beep_time);        
      }
        
  }
  else if(dosedone==1)// dosing finished within tolerance
  {
    Serial.println(F("Dose finished"));
    lcd.setCursor(0,0);
    strcpy_P(PufferChar, (char *)pgm_read_word(&(str_dosedone[Language])));
    lcd.print(PufferChar);
    lcd_print_weight(W_actual,8,1);
    for(int i= 0;i<=(2*right_dose)-1;i++) //Beeps for overdose
      {
       digitalWrite(BUZZsig, !digitalRead(BUZZsig)); 
       delay(beep_time);        
      }
    delay(1500);
  }
  else // dosing endet with error
  {
    button_off(SW4);
    Serial.println(F("stopped||timeout")); //
    lcd.setCursor(0,0);
    strcpy_P(PufferChar, (char *)pgm_read_word(&(str_timeout[Language])));
    lcd.print(PufferChar);
    lcd_print_weight(W_actual,8,1);
    for(int i= 0;i<=(2*failed_dose)-1;i++) //Beeps for overdose
      {
       digitalWrite(BUZZsig, !digitalRead(BUZZsig)); 
       delay(beep_time);        
      }
  }
lcd.clear();
}


void mymenu() // start the menu
{
  Serial.println(F("enter Menu")); //
  menuon=1;
  menuentry=0;
  delay(100); // wait buuton to be fully switched, keybounce protection
  button_off(SW1); //wait until button one is released
 
  while(menuon) //stay here until menu will be left
  {
    menuupdate=0;
    //update Menu textes
    // if menuentry  <0 or >number of entrys
    if (menuentry < 0){menuentry= numberofentrys-1;}
    if (menuentry > numberofentrys-1){menuentry=0;}
     
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(F(">"));
    lcd.print(menu[menuentry]);
    Serial.println(menu[menuentry]); //
   
  while(menuon && !menuupdate)
  {
   //while wait für buttons to do something
    if(analogRead(A0) < noSWpressed)
    {
      delay(10);
      a0value= analogRead(A0);
      if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)// Enter is pressed do something
        {
         button_off(SW5);
         lcd.clear();
         lcd.setCursor(1,0);
         lcd.print(menu[menuentry]);
         lcd.setCursor(0,1);
         lcd.print(F(">"));
         switch(menuentry) //decide what to do
          {
          case 0: // load memory submenu
          memory_load();
          break; // event on clicked menu point
          case 1: //save memorys submenu
          memory_save(); // event on clicked menu point
          break;
          case 2:// calibrate scale submenu & event
          submenu_calibrate();
          break;
          case 3:// change unit (gramm to grain)
          submenu_unit();
          break;
          case 4:
          submenu_autotara();
          break;
          case 5:
          submenu_dosefast();
          break;
          case 6:
          submenu_doseslow();
          break;
          case 7:
          submenu_rampstart();
          break;
          case 8:
          submenu_rampend();
          break;
          case 9:
          submenu_tolerance();
          break;
          case 10:
          submenu_language();
          break;
          case 11:
          submenu_reset();
          break;
          default:
         
          break;
          }
        }
       
      if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
        {
        menuentry++;
        button_off(SW3);//wait until button one is released 
        menuupdate=1;
        }
      if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
        {
        menuentry--;
        button_off(SW2);
        menuupdate=1;
        }
      if(a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)//menu button is tipped, leave the menu
        {
         lcd.clear();
         button_off(SW1);
         menuon=0;
        }
    }
  
  }
 
  }//leaving menu
  Serial.println(F("Exit Menu")); //

 
}


void memory_save()//the hole  submenu  when saving a memory
{
            strcpy_P(PufferChar, (char *)pgm_read_word(&(str_memory[Language])));
            lcd.print(PufferChar);
            lcd.setCursor(14,1);
            lcd.print(memlocation+1);
            submenuon=1;
            while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if(a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)
                {
                  button_off(SW1);
                  a0value= analogRead(A0);
                  menuupdate=1;
                  submenuon=0;
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  button_off(SW2);
                  memlocation++;
                  if (memlocation >= memspace-1){memlocation = memspace-1;}
                  lcd.setCursor(14,1);
                  lcd.print(memlocation+1);
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  button_off(SW3);
                  memlocation--;
                  if (memlocation < 0){memlocation= 0;}
                  lcd.setCursor(14,1);
                  lcd.print(memlocation+1);
                }
                if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)
                {
                  button_off(SW5);
                  EEPROM.put(address_memory[memlocation], W_Setpoint);
                  lcd.clear();
                  lcd.setCursor(0,1);
                  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_memsave[Language])));
                  lcd.print(PufferChar);
                  delay(1500);
                  lcd.clear();
                  menuon=0;
                  submenuon=0;
              }
              }
          }
  }

void memory_load()//whole submenu event for memory loading
{
            strcpy_P(PufferChar, (char *)pgm_read_word(&(str_memory[Language])));
            lcd.print(PufferChar);
            lcd.setCursor(14,1);
            lcd.print(memlocation+1);
            submenuon=1;
            while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if(a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)
                {
                  button_off(SW1);
                  a0value= analogRead(A0);
                  menuupdate=1;
                  submenuon=0;
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  button_off(SW2);
                  memlocation++;
                  if (memlocation >= memspace-1){memlocation = memspace-1;}
                  lcd.setCursor(14,1);
                  lcd.print(memlocation+1);
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  button_off(SW3);
                  memlocation--;
                  if (memlocation < 0){memlocation= 0;}
                  lcd.setCursor(14,1);
                  lcd.print(memlocation+1);
                }
                if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)
                {
                  button_off(SW5);
                  EEPROM.get(address_memory[memlocation],W_Setpoint );
                  menuon=0;
                  submenuon=0;
              }
              }
          }
}

void submenu_calibrate()
{
          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_ask[Language])));
          lcd.print(PufferChar);
          submenuon=1;
          while(submenuon)
          {
            if(analogRead(A0) < noSWpressed)
              {
              delay(10);
              a0value= analogRead(A0);
              if(a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)
              {
                button_off(SW1);
                a0value= analogRead(A0);
                menuupdate=1;
                submenuon=0;
               
              }
              if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)
              {
                button_off(SW5);
                lcd.clear();
                scalecalibration();
                menuon=0;
                submenuon=0;
              }
              }
          }
}

void submenu_unit()
{
            if(scaleunit==0)
            {
            lcd.print(" g");
            }
            else
            {
            lcd.print("gn");
            }
            submenuon=1;
            while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  menuupdate=1;
                  submenuon=0;
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  button_off(SW2);
                  if(scaleunit==1)
                  {
                  lcd.setCursor(1,1);
                  lcd.print(" g");
                  scaleunit=0;
                  ScaleFactor= ScaleFactor*gr_gn;
                  startramp= (float)((long)(startramp/gr_gn*1000L))/(1000);
                  endramp= (float)((long)(endramp/gr_gn*1000L))/(1000);
                  tolerance= (float)((long)(tolerance/gr_gn*1000L))/(1000);
                  updatememory=1;
                  for(int i= 0;i<=memspace-1;i++)
                  {
                  EEPROM.get(address_memory[i], W_Setpoint);
                  W_Setpoint= (float)((long)(W_Setpoint/gr_gn*1000L))/(1000);
                  EEPROM.put(address_memory[i], W_Setpoint);
                  }
                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  button_off(SW3);
                  if(scaleunit==0)
                  {
                  lcd.setCursor(1,1);
                  lcd.print("gn");
                  scaleunit=1;
                  ScaleFactor= ScaleFactor/gr_gn;
                  startramp= (float)((long)(startramp*gr_gn*100L))/(100);
                  endramp= (float)((long)(endramp*gr_gn*100L))/(100);
                  tolerance= (float)((long)(tolerance*gr_gn*100L))/(100);
                  updatememory=1;
                  for(int i= 0;i<=memspace-1;i++)
                  {
                  EEPROM.get(address_memory[i], W_Setpoint);
                  W_Setpoint= (float)((long)(W_Setpoint*gr_gn*100L))/(100);
                  EEPROM.put(address_memory[i], W_Setpoint);
                  }
                 
                  }
                 
                }
                  if(updatememory)
                  {
                  EEPROM.put(address_ScaleFactor, ScaleFactor);
                  EEPROM.put(address_startramp, startramp);
                  EEPROM.put(address_endramp, endramp);
                  EEPROM.put(address_tolerance, tolerance);
                  EEPROM.put(address_scaleunit, scaleunit);
                  scale.set_scale(ScaleFactor);
                  EEPROM.get(address_memory[0], W_Setpoint);
                  updatememory=0;
                  }
              }
          }
 
}



void submenu_autotara()
{
            if(autotara==0)
            {
            strcpy_P(PufferChar, (char *)pgm_read_word(&(str_off[Language])));
            lcd.print(PufferChar);
            }
            else
            {
            strcpy_P(PufferChar, (char *)pgm_read_word(&(str_on[Language])));
            lcd.print(PufferChar);
            }
            //while(!((analogRead(0) > SW5+swtolerance) || (analogRead(0) < SW5-swtolerance)));
            submenuon=1;
            while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  menuupdate=1;
                  submenuon=0;
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  button_off(SW2);
                  if(autotara==1)
                  {
                  lcd.setCursor(1,1);
                  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_off[Language])));
                  lcd.print(PufferChar);
                  lcd.print(F(" "));
                  autotara=0;
                  EEPROM.put(address_autotara, autotara);
                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  button_off(SW3);
                 
                  if(autotara==0)
                  {
                  lcd.setCursor(1,1);
                  strcpy_P(PufferChar, (char *)pgm_read_word(&(str_on[Language])));
                  lcd.print(PufferChar);
                  lcd.print(F(" "));
                  autotara=1;
                  EEPROM.put(address_autotara, autotara);
                  }
                 
                  }
                 
                }
              }
}
 

void submenu_dosefast()
{
  lcd.setCursor(3,1);
  lcd.print(maxspeed);
  submenuon=1;
  while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  EEPROM.put(address_maxspeed, maxspeed);
                  menuupdate=1;
                  submenuon=0;
                
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  maxspeed =speed_change_acc(SW2, maxspeed, 1.0, 3, 1);
                  button_off(SW2);

                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  maxspeed =speed_change_acc(SW3, maxspeed, -1.0, 3, 1);
                  button_off(SW3);
                 
                 
                 
                  }
                 
                }
              }




             
Kod bardzo długi więc musiałem podzielić na dwie częsci:
Kod:
void submenu_doseslow()
{
  lcd.setCursor(3,1);
  lcd.print(minspeed);
  submenuon=1;
  while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  EEPROM.put(address_minspeed, minspeed);
                  menuupdate=1;
                  submenuon=0;
                
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  minspeed =speed_change_acc(SW2, minspeed, 1.0, 3, 1);
                  button_off(SW2);

                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  minspeed =speed_change_acc(SW3, minspeed, -1.0, 3, 1);
                  button_off(SW3);
                 
                 
                 
                  }
                 
                }
              }

void submenu_rampstart()
{
  lcd_print_weight(startramp,3, 1);
  submenuon=1;
  while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  EEPROM.put(address_startramp, startramp);
                  menuupdate=1;
                  submenuon=0;
                
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  startramp =  weight_change_acc(SW2,startramp, 0.001,0.01, 3, 1);
                  button_off(SW2);

                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  startramp = weight_change_acc(SW3,startramp,-0.001,-0.01, 3, 1);
                  button_off(SW3);
                  }
                 
                }
              }



void submenu_rampend()
{
  lcd_print_weight(endramp,3, 1);
  submenuon=1;
  while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  EEPROM.put(address_endramp, endramp);
                  menuupdate=1;
                  submenuon=0;
                
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  endramp =  weight_change_acc(SW2,endramp, 0.001,0.01, 3, 1);
                  button_off(SW2);

                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  endramp = weight_change_acc(SW3,endramp,-0.001,-0.01, 3, 1);
                  button_off(SW3);
                  }
                 
                }
              }

void submenu_tolerance()
{
  lcd_print_weight(tolerance,3, 1);
  submenuon=1;
  while(submenuon)
            {
           
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                  EEPROM.put(address_tolerance, tolerance);
                  menuupdate=1;
                  submenuon=0;
                
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  tolerance =  weight_change_acc(SW2,tolerance, 0.001,0.01, 3, 1);
                  button_off(SW2);

                  }
                 
         
               
                }
                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  tolerance = weight_change_acc(SW3,tolerance,-0.001,-0.01, 3, 1);
                  button_off(SW3);
                  }
                 
                }
              }

void submenu_reset()
{
          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_ask[Language])));
          lcd.print(PufferChar);
          submenuon=1;
          while(submenuon)
          {
            if(analogRead(A0) < noSWpressed)
              {
              delay(10);
              a0value= analogRead(A0);
              if(a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)
              {
                button_off(SW1);
                a0value= analogRead(A0);
                menuupdate=1;
                submenuon=0;
               
              }
              if(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance)
              {
                button_off(SW5);
                lcd.clear();
                for(int c=0; c<=255; c++)
                {
                EEPROM.put(c, 0);
                }//end of for
                lcd.setCursor(0,0);
                lcd.print(F("reset finished"));
                lcd.setCursor(0,1);
                lcd.print(F("unplug loader"));
                while(1)
                {
                 }
              }
              }
          }
}


void submenu_language()
{
            submenuon=1;
            new_Language=Language;
            while(submenuon)
            {
                          lcd.clear();
                          lcd.setCursor(1,0);
                          lcd.print(menu[menuentry]);
                          lcd.setCursor(0,1);
                          lcd.print(F(">"));
                          submenuupdate=0;
                          if(new_Language<0){new_Language=number_languages-1;}
                          if(new_Language>(number_languages-1)){new_Language=0;}
                          if(new_Language==0)
                          {
                          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_english[Language])));
                          }
                          else if (new_Language==1)
                          {
                          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_2ndlanguage[Language])));
                          }
                          else
                          {
                          strcpy_P(PufferChar, (char *)pgm_read_word(&(str_3ndlanguage[Language])));
                          }
                          lcd.print(PufferChar);
                         
              while(submenuon && !submenuupdate)  
              {      
              if(analogRead(A0) < noSWpressed)
                {
               delay(10);
               a0value= analogRead(A0);
                if((a0value >= SW1-swtolerance && a0value <= SW1+swtolerance)||(a0value >= SW5-swtolerance && a0value <= SW5+swtolerance))
                {
                  if (Language!=new_Language)
                  {
                  Language=new_Language;
                  EEPROM.put(address_Language, Language);
                  language();
                  }
                  button_off(SW1);
                  button_off(SW5);
                  a0value= analogRead(A0);
                 
                  menuupdate=1;
                  submenuon=0;
                }
                if(a0value >= SW2-swtolerance && a0value <= SW2+swtolerance)
                {
                  button_off(SW2);
                  new_Language++;
                  submenuupdate=1;
                
                  }

                if(a0value >= SW3-swtolerance && a0value <= SW3+swtolerance)
                {
                  button_off(SW3);
                  new_Language--;
                  submenuupdate=1;
                 
                  }
                 
                }
              }
              }


 
}





void lcd_print_weight(float weight,byte lcd_cursor, byte lcd_line) //prints a weight with unit, limits it , 8 spaces needed
{
if(scaleunit==0||scalecalib>0)
  {
  if(weight>99.999){weight = 99.999;}
  if(weight<-9.999){weight = -9.999;}
  show_dec=3;
  lcd.setCursor(lcd_cursor+6,lcd_line);
  lcd.print(F(" g"));

}
else
{
  if(weight>999.99){weight = 999.99;}
  if(weight<-99.99){weight = -99.99;}
  show_dec=2;
  lcd.setCursor(lcd_cursor+6,lcd_line);
  lcd.print(F("gn"));
}
dtostrf(weight, 6, show_dec,PufferChar);
lcd.setCursor(lcd_cursor,lcd_line);
lcd.print(PufferChar);
}

void button_off(int sw) // waits until the button is released
{
while(!((a0value > sw+swtolerance) || (a0value < sw-swtolerance)))
{a0value= analogRead(A0);}
//delay(10);
//a0value= analogRead(A0);
}
 
Użyj płytki UNO bez bootloadera, ustaw wyższe definicje optymalizacji i powinno się zmieścić, przecież w oryginale ktoś to kompilował i wgrywał. Czasami wybór innego core może pomóc, Atmega328p jest w miniCore. Będziesz potrzebował programatora by wtedy wgrać, jakiś USBASP to koszt z 15zł.
O, nawet niewiele brakuje w oryginale, mi wyszło 32480, a max to 32256 + 512 zajmowane przez bootloader.
Kod:
Szkic używa 32480 bajtów (100%) pamięci programu. Maksimum to 32256 bajtów.text section exceeds available space in board

Zmienne globalne używają 1344 bajtów (65%) pamięci dynamicznej, pozostawiając 704 bajtów dla zmiennych lokalnych. Maksimum to 2048 bajtów.
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
Błąd kompilacji dla płytki Arduino Uno.
Ja to chyba już kiedyś kompilowałem, ale mam inny komp teraz, w Core mini właśnie nie poszło, bo zajmowało więcej, musiałem dodać sobie definicję płytki z Atmega328p do core AVR bez bootloadera i wtedy się skompilowało.
Poszukam w archiwum.

Dobra, robiłem to w Win7, trzeba znaleźć w katalogu instalacji Arduino plik boards.txt, tam po uno dokleić kolejną sekcję dla płytki z Atmega328p bez bootloadera i dla niej skompilować, wgrać programatorem:
Kod:
######################################################
328NoBL.name=328PNoLoader

328NoBL.vid.0=0x2341
328NoBL.pid.0=0x0043
328NoBL.vid.1=0x2341
328NoBL.pid.1=0x0001
328NoBL.vid.2=0x2A03
328NoBL.pid.2=0x0043
328NoBL.vid.3=0x2341
328NoBL.pid.3=0x0243

328NoBL.upload.tool=avrdude
328NoBL.upload.protocol=arduino
328NoBL.upload.maximum_size=32768
328NoBL.upload.maximum_data_size=2048
328NoBL.upload.speed=115200

328NoBL.bootloader.tool=avrdude
328NoBL.bootloader.low_fuses=0xFF
328NoBL.bootloader.high_fuses=0b1101 111
328NoBL.bootloader.extended_fuses=0xFD
328NoBL.bootloader.unlock_bits=0x3F
328NoBL.bootloader.lock_bits=0x0F
328NoBL.bootloader.file=optiboot/optiboot_atmega328.hex

328NoBL.build.mcu=atmega328p
328NoBL.build.f_cpu=16000000L
328NoBL.build.board=AVR_UNO
328NoBL.build.core=arduino
328NoBL.build.variant=standard

##############################################################
W Win10 jest taki problem, że ten plik jest u mnie z zabronionym dostępem. Trzeba przejąć do niego uprawnienia, teraz z tym nie powalczę, prościej jest ściągnać wersję Arduino portable i sobie w nim to ustawić.
No właśnie mam win 10 i nie mogę tego pliku odnaleźć.
Poza tym, nie mam pojęcia jak użyć tej płytki bez boatloadera.
Używam Arduino IDE.
No to sobie ściągnij wersję portable. Jak zaprogramować płytkę UNO programatorem znajdziesz tutoriale na Youtube, albo obrazkowe na blogach, użyj Google - usbasp UNO. Taka waga do robienia naważek proszków to i tak kikaset zł w wersji DIY lub parę tysięcy komercyjna, programator to 15zł. Nie twierdzę, że będzie łatwo.
Na uno R3 śmiga jak nalezy.

Czy żywcem wrzucony kod do Arduino UNO R4 minima powinien działać bez przeróbek?
Bo próbuje lecz działać nie chce.
Proste programy mogą zadziałać, a z tego co piszesz to nie wiele wiadomo. Na R3 śmiga bo ...? Samo się naprawiło?
A R4 to zupełnie inna rodzina uC, nie działa bo...? Nie działa to bym powiedział, że kod się skompilował, wgrał, lecz , no właśnie, nie działa. A to Ci się na jakim etapie zrobiło "nie działa", jakie są tego objawy, pokazuje coś na UART, czy zimny trup?
Na R3 okroilem trochę kod, zmieścił się i waga śmiga.

Jeśli chodzi o R4 to kompiluje, wgrywam i nie wyskakuje żaden błąd.
Za to przy uruchomieniu wagi nie reaguje ona ani na przyciski ani na tensometr.
Na wyświetlaczu pokazują się napisy o wadze zadanej i liczba 000 oraz waga aktualna 999,99
Dodaj sobie drukowanie na serial komunikatów to się dowiesz, w którym miejscu program przestaje się wykonywać.
(28-12-2024, 01:12)kaczakat napisał(a): [ -> ]Dodaj sobie drukowanie na serial komunikatów to się dowiesz, w którym miejscu program przestaje się wykonywać.

Serial monitor pokazuje mi tylko tyle:
Cytat:Button pressed

End Switch Calibration

Scale Memory loaded

Setup finished
Stron: 1 2