Library optimieren/straffen

Guten Abend miteinander,
Ich habe hier die SSD1306_Minimal Lib , die speziel für die Attiny's geschrieben ist, etwas umgebaut. 1. ich habe anstatt der TinyWire wieder die Wire eingebunden da ich den Attiny-Core von SpenceKonde nutze, und dieser eine auf den Attinys laufende Wire im Core beigelegt hat. Zudem hatte ich , sobald ich den Attiny 167 als Board/Prozessor gewählt habe, mit der TinyWire Probleme , diese zu kompilieren. Da ich auch noch weitere i2C-Sensoren und ne DS3132 am Attiny habe und ich wollte auch nicht 2 verschiedene Wire-libs verwenden.
Als mit der Zeit, während das Projekt fortschritt, der Flash im Attiny etwas voller wurde, habe ich mich entschieden, den Zeichensatz so wie die von mir entworfenen Symbole und Icons/Cliparts aus dem PROGMEM zu werfen und in ein I2C-EEPROM auszulagern. Dies erlaupte mir dann auch gleichzeitig, einen 2. Zeichensatz , den ich in der Titelzeile der Menues nutze, einzubinden. I
Somit habe ich also aus der SSD11306_Minimal Lib die SSD1306_Minimal_EROM lib gesbastelt. Diese liest nun den Zeichensatz (die Zeichensätze) nicht mehr aus dem PROGMEM sondern aus dem I2C EEPROM. Ebenfalls die Bitmap-Grafiken, die original ebenfalls im Flash liegen.
In der vorliegenden version habe ich die EEprom-Grösse von der Adressbreite her auf 64 KByte , also uint16 begrenzt, da ich auch den Ram Verbrauch kleinhalten will/muss.

Hier die SSD1306_minimal_erom.h

/*

  SSD1306_minimal.h - SSD1306 OLED Driver Library
  2015 Copyright (c) CoPiino Electronics All right reserved.

  Original Author: GOF Electronics Co. Ltd.
  Modified by: CoPiino Electronics ( http://copiino.cc )

  CoPiino Electronics invests time and resources providing this open source code,
	please support CoPiino Electronics and open-source hardware by purchasing
	products from CoPiino Electronics!

  What is it?
    This library is derived from GOFi2cOLED library, only for SSD1306 in I2C Mode.
    As the original library only supports Frame Buffered mode which requires to have
    at least 1024bytes of free RAM for a 128x64px display it is too big for smaller devices.

    So this a SSD1306 library that works great with ATTiny85 devices :)


  It is a free software; you can redistribute it and/or modify it
  under the terms of BSD license, check license.txt for more information.
	All text above must be included in any redistribution.

  Modified by: SMC
  Modifying to opperate with external I2C EPprom/FRAM (naed as ERom) for Fonts and  Icons/Cliparts

*/


#ifndef __SSD1306_MINIMAL_EROM_H__
#define __SSD1306_MINIMAL_EROM_H__

#include <Arduino.h>

// config
//#define SlaveAddress 0x3c
//#define RomAddress  0x50

#include <Wire.h>

// defines taken from GOFi2cOLED
#define GOFi2cOLED_Command_Mode		    0x80
#define GOFi2cOLED_Data_Mode		      0x40

//Fundamental Command (more than one bytes command pleaserefer to SSD1306 datasheet for details)
#define Set_Contrast_Cmd                      0x81     //Double byte command to select 1 out of 256 contrast steps.Default(RESET = 0x7F)
#define Entire_Display_On_Resume_Cmd          0xA4     //Resume to RAM content display(RESET), Output follows RAM content
#define Entire_Display_On_Cmd                 0xA5     //Entire display ON, Output ignores RAM content
#define GOFi2cOLED_Normal_Display_Cmd	      0xA6     //Normal display (RESET)
#define GOFi2cOLED_Inverse_Display_Cmd	      0xA7     //Inverse display
#define GOFi2cOLED_Display_Off_Cmd	      0xAE     //sleep mode(RESET)
#define GOFi2cOLED_Display_On_Cmd	      0xAF     //normal mode

//Scrolling Command (more than one bytes command pleaserefer to SSD1306 datasheet for details)
#define Right_Horizontal_Scroll_Cmd           0x26
#define Left_Horizontal_Scroll_Cmd            0x27
#define Vertical_Right_Horizontal_Scroll_Cmd  0x29
#define Vertical_Left_Horizontal_Scroll_Cmd   0x2A
#define Activate_Scroll_Cmd                   0x2F
#define Deactivate_Scroll_Cmd                 0x2E
#define Set_Vertical_Scroll_Area_Cmd          0xA3

//Addressing Setting Command (more than one bytes command pleaserefer to SSD1306 datasheet for details)
#define Set_Memory_Addressing_Mode_Cmd        0x20
#define HORIZONTAL_MODE			      0x00
#define VERTICAL_MODE			      0x01
#define PAGE_MODE			      0x02       //Default(reset)
#define Set_Column_Address_Cmd                0x21       //Setup column start and end address. This command is only for horizontal or vertical addressing mode.
#define Set_Page_Address_Cmd                  0x22       //Setup page start and end address. This command is only for horizontal or vertical addressing mode.

//Hardware Configuration (Panel resolution & layout related) Command (more than one bytes command please refer to SSD1306 datasheet for details)
#define Segment_Remap_Cmd                     0xA1       //column address 127 is mapped to SEG0
#define Segment_Normal_map_Cmd                0xA0       //Default. column address 0 is mapped to SEG0(RESET)
#define Set_Multiplex_Ratio_Cmd               0xA8       //Set MUX ratio to N+1 MUX
#define COM_Output_Normal_Scan_Cmd            0xC0       //Normal mode (RESET). Scan from COM0 to COM[N �C1]
#define COM_Output_Remap_Scan_Cmd             0xC8       //Remapped mode. Scan from COM[N-1] to COM0
#define Set_Display_Offset_Cmd                0xD3       //Set vertical shift by COM from 0d~63d. The value is reset to 00h after RESET.
#define Set_COM_Pins_Hardware_Config_Cmd      0xDA

//Timing & Driving Scheme Setting Command (more than one bytes command pleaserefer to SSD1some more than one bytes command please 306 datasheet for details)
#define Set_Display_Clock_Divide_Ratio_Cmd    0xD5
#define Set_Precharge_Period_Cmd              0xD9
#define Set_VCOMH_Deselect_Level_Cmd          0xDB
#define No_Operation_Cmd                      0xE3

#define Charge_Pump_Setting_Cmd      	      0x8D
#define Charge_Pump_Enable_Cmd	              0x14
#define Charge_Pump_Disable_Cmd               0x10     //default

#define Scroll_Left			      0x00
#define Scroll_Right			      0x01

#define Scroll_2Frames			      0x7
#define Scroll_3Frames			      0x4
#define Scroll_4Frames			      0x5
#define Scroll_5Frames			      0x0
#define Scroll_25Frames			      0x6
#define Scroll_64Frames			      0x1
#define Scroll_128Frames		      0x2
#define Scroll_256Frames		      0x3

#define Dummy_Byte_0x00                       0x00
#define Dummy_Byte_0xFF                       0xFF

//
class SSD1306_Mini {

  public:

    // call this function once in "void setup()" to initiallize the display
    void init(uint8_t dispaddr, uint8_t eromaddr);

    // switch the display PixelLeds on
    void displayOn();

    // switch the display PixelLeds off (low current mode)
    void displayOff();

    // reset clipArea to maximum and clear the display
    void clear();

    // move cursor to upper left corner in current clipArea
    void startScreen();


    // set the clipArea, by default (0,0,128,8)
    void clipArea(unsigned char col, unsigned char row, unsigned char w, unsigned char h);

    // change the active Font (0 = BasicFont  ,  1 = BoldFont)
    void setFont( bool font );

    // move the cursor to a location (similar to clipArea)
    void cursorTo( unsigned char row, unsigned char col );

    // print a single character
    void printChar( char ch );

    // print a string to the screen
    void printString( const char * pText );

    // draw an image with defined x,y position and width,height definition
    void drawImage( uint16_t img, unsigned char col, unsigned char row, unsigned char w, unsigned char h );

    //
    //void displayX(int off);

    //  private:
    void sendCommand(unsigned char command);
    void sendData(unsigned char Data);
    void getERom (uint16_t romAddr, byte Bytes);

    uint32_t getImgAddr (uint16_t img);
    byte rombuf[8];
};


#endif

Und hier die SSD1306_minimal_erom.cpp

/*
  SSD1306_minimal.h - SSD1306 OLED Driver Library
  2015 Copyright (c) CoPiino Electronics All right reserved.

  Original Author: GOF Electronics Co. Ltd.
  Modified by: CoPiino Electronics ( http://copiino.cc )

  CoPiino Electronics invests time and resources providing this open source code,
	please support CoPiino Electronics and open-source hardware by purchasing
	products from CoPiino Electronics!

  What is it?
    This library is derived from GOFi2cOLED library, only for SSD1306 in I2C Mode.
    As the original library only supports Frame Buffered mode which requires to have
    at least 1024bytes of free RAM for a 128x64px display it is too big for smaller devices.

    So this a SSD1306 library that works great with ATTiny85 devices :)


  It is a free software; you can redistribute it and/or modify it
  under the terms of BSD license, check license.txt for more information.
	All text above must be included in any redistribution.
*/

#include "SSD1306_minimal_erom.h"

#define BasicFont 0
#define BoldFont1 1019


uint8_t SlaveAddress;  // i2c Adresse Display
uint8_t RomAddress;   // i2c Adresse Charakter Rom (eeprom/fram)

byte charwidth = 5;
uint16_t FontAddr = BasicFont;

void SSD1306_Mini::getERom(uint16_t romAddr, byte bytes) {
  Wire.beginTransmission(RomAddress);
  Wire.write(romAddr >> 8);
  Wire.write(romAddr);
  Wire.endTransmission();
  Wire.requestFrom(RomAddress, (byte) bytes);
  for (byte i = 0; i < bytes; i++) {
    rombuf[i] = (Wire.read());
  }
}

uint32_t SSD1306_Mini::getImgAddr (uint16_t img) {
  Wire.beginTransmission(RomAddress);
  Wire.write(img >> 8);
  Wire.write(img);
  Wire.endTransmission();
  Wire.requestFrom(RomAddress, (byte)2);
  return (256 * Wire.read() + Wire.read());
}

void SSD1306_Mini::sendCommand(unsigned char command)
{
  Wire.begin();                       //initialize I2C
  Wire.beginTransmission(SlaveAddress); // begin I2C communication

  Wire.write(GOFi2cOLED_Command_Mode);	     // Set OLED Command mode
  Wire.write(command);
  Wire.endTransmission();    		     // End I2C communication
}

void SSD1306_Mini::sendData(unsigned char Data)
{
  Wire.begin();                    //initialize I2C
  Wire.beginTransmission(SlaveAddress); // begin I2C transmission
  Wire.write(GOFi2cOLED_Data_Mode);            // data mode
  Wire.write(Data);
  Wire.endTransmission();                    // stop I2C transmission
}

void SSD1306_Mini::init(uint8_t dispaddr, uint8_t eromaddr)
{

  Wire.begin();

  delay(5);	//wait for OLED hardware init
  // constructor(128, 64);
  SlaveAddress = dispaddr;
  RomAddress = eromaddr;
  sendCommand(GOFi2cOLED_Display_Off_Cmd);    /*display off*/

  sendCommand(Set_Multiplex_Ratio_Cmd);    /*multiplex ratio*/
  sendCommand(0x3F);    /*duty = 1/64*/

  sendCommand(Set_Display_Offset_Cmd);    /*set display offset*/
  sendCommand(0x00);

  sendCommand(Set_Memory_Addressing_Mode_Cmd); 	//set addressing mode
  sendCommand(HORIZONTAL_MODE); 			//set horizontal addressing mode

  sendCommand(0xB0); 			//set page address
  sendCommand(0x00); 	//set column lower address
  sendCommand(0x10); 	//set column higher address

  sendCommand(0x40);    /*set display starconstructort line*/

  sendCommand(Set_Contrast_Cmd);    /*contract control*/
  sendCommand(0xcf);    /*128*/

  sendCommand(Segment_Remap_Cmd);    /*set segment remap*/

  sendCommand(COM_Output_Remap_Scan_Cmd);    /*Com scan direction*/

  sendCommand(GOFi2cOLED_Normal_Display_Cmd);    /*normal / reverse*/

  sendCommand(Set_Display_Clock_Divide_Ratio_Cmd);    /*set osc division*/
  sendCommand(0x80);

  sendCommand(Set_Precharge_Period_Cmd);    /*set pre-charge period*/
  sendCommand(0xf1);

  sendCommand(Set_COM_Pins_Hardware_Config_Cmd);    /*set COM pins*/
  sendCommand(0x12);

  sendCommand(Set_VCOMH_Deselect_Level_Cmd);    /*set vcomh*/
  sendCommand(0x30);

  sendCommand(Deactivate_Scroll_Cmd);

  sendCommand(Charge_Pump_Setting_Cmd);    /*set charge pump enable*/
  sendCommand(Charge_Pump_Enable_Cmd);

  sendCommand(GOFi2cOLED_Display_On_Cmd);    /*display ON*/
}

void SSD1306_Mini::displayOn() {
  sendCommand(GOFi2cOLED_Display_On_Cmd);
}

void SSD1306_Mini::displayOff() {
  sendCommand(GOFi2cOLED_Display_Off_Cmd);
}

void SSD1306_Mini::setFont( bool font ) {
  charwidth = 5;
  FontAddr = BasicFont;
  if (font) {
    charwidth = 8;
    FontAddr = BoldFont1;
  }
}

void SSD1306_Mini::clipArea(unsigned char col, unsigned char row, unsigned char w, unsigned char h) {

  Wire.begin();                           // initialize I2C
  Wire.beginTransmission(SlaveAddress);   // begin I2C transmission
  Wire.write(GOFi2cOLED_Command_Mode);    // data mode
  Wire.write(Set_Column_Address_Cmd);
  Wire.write(0);

  Wire.write(col);
  Wire.write(col + w - 1);

  Wire.endTransmission();                  // stop I2C transmission

  Wire.begin();                            // initialize I2C
  Wire.beginTransmission(SlaveAddress);    // begin I2C transmission
  Wire.write(GOFi2cOLED_Command_Mode);     // data mode
  Wire.write(Set_Page_Address_Cmd);
  Wire.write(0);

  Wire.write(row);
  Wire.write(row + h - 1);

  Wire.endTransmission();                   // stop I2C transmission

}

void SSD1306_Mini::cursorTo(unsigned char col, unsigned char row) {
  clipArea(col, row, 128 - col, 8 - row);
}

void SSD1306_Mini::startScreen() {

  sendCommand(0x00 | 0x0);  // low col = 0
  sendCommand(0x10 | 0x0);  // hi col = 0
  sendCommand(0x40 | 0x0); // line #0
}

void SSD1306_Mini::clear() {

  sendCommand(0x00 | 0x0);  // low col = 0
  sendCommand(0x10 | 0x0);  // hi col = 0
  sendCommand(0x40 | 0x0); // line #0

  clipArea(0, 0, 128, 8);

  for (uint16_t i = 0; i <= ((128 * 64 / 8) / 16); i++)
  {
    // send a bunch of data in one xmission
    Wire.beginTransmission(SlaveAddress);
    Wire.write(GOFi2cOLED_Data_Mode);            // data mode
    for (uint8_t k = 0; k < 16; k++) {
      Wire.write( 0 );
    }
    Wire.endTransmission();
  }
}

void SSD1306_Mini::displayX(int off) {
  sendCommand(0x00 | 0x0);  // low col = 0
  sendCommand(0x10 | 0x0);  // hi col = 0
  sendCommand(0x40 | 0x0); // line #0

  for (uint16_t i = 0; i <= ((128 * 64 / 8) / 16); i++)
  {
    // send a bunch of data in one xmission
    Wire.beginTransmission(SlaveAddress);
    Wire.write(GOFi2cOLED_Data_Mode);            // data mode
    for (uint8_t k = 0; k < 16; k++) {
      Wire.write( i * 16 + k + off);
    }
    Wire.endTransmission();
  }
}

void SSD1306_Mini::printChar( char ch ) {

  unsigned char i = ch;
  getERom(FontAddr + (i * charwidth), charwidth);

  Wire.beginTransmission(SlaveAddress);
  Wire.write(GOFi2cOLED_Data_Mode);            // data mode

  Wire.write( 0x00 );
  Wire.write( rombuf, charwidth );
  if (charwidth == 5) Wire.write( 0x00 );
  Wire.endTransmission();
}

void SSD1306_Mini::printString( const char * pText ) {
  unsigned char i;
  unsigned char len = strlen( pText );

  for (i = 0; i < len; i++) {
    printChar( pText[i] );
  }
}

void SSD1306_Mini::drawImage( uint16_t img, unsigned char col, unsigned char row, unsigned char w, unsigned char h ) {
  unsigned char i, imgsize, bufsize, rest;

  img = getImgAddr (img);
  clipArea( col, row, w, h);
  imgsize = w * h;
  bufsize = 8;                                // blockgrösse

  rest = (imgsize) % bufsize;                   // wenn nein, rest merken
  for (i = 0; i < (imgsize); i += bufsize) {
    if (i == imgsize - rest) bufsize = rest;      // buffer auf restliche Bytes setzen
    getERom (img + i, bufsize);               // symbol blockweise lesen
    Wire.beginTransmission(SlaveAddress);
    Wire.write(GOFi2cOLED_Data_Mode);         // data mode
    Wire.write(rombuf, bufsize);              // symbol blockweise ins Display
    Wire.endTransmission();
  }
}

Noch eine kleine Anmerkung: An die Funktion .drawImage wird nicht direkt die Startadresse der jewieligen Bitmap im EEPROM übergeben, sondern die (16bit) Adresse in der Bitmap-Adress-Table, also einer Tabelle in der die Positionen aller Bitmaps , die mit drawImage gezeichnet werden können , vermerkt ist. Die Lib selber weiss also nicht, wo im EEprom die Adresstabelle oder die Symbole selbst gespeichert sind. für die Zeichensätze sind die Startadressen in der Lib eingetragen.

Jetzt die Frage: wie kann ich die Library bei gleichem Funktionsumfang, noch weiter staffen/optimieren in Bezug auf die grösse im Flash?
Und , falls möglich ist es nicht schlimm, wenn auch noch das eine , oder andere Byte im RAM gespart wird. Wobei der RAM im Attiny noch locker ausreichend ist, Da ich im Hauptcode recht sparsam mit dem RAM umgehe.

warum macht man so was? Mach dich unabhängig von einer speziellen Wire Lib. Binde die Wire im Usersketch ein oder schaff die Möglichkeit ein Wire Objekt im Konstruktor zu übergeben.

Dann kann jeder User selber entscheiden, welche Wire für ihn passt.

Auch verstehe ich nicht warum es mehrere Wire.begin() braucht. Am besten macht man gar kein Wire.begin in einer lib sondern macht das einmal im Setup des Sketch.

Befolge dir Ratschläge von Sparkfun und folge den Deeplinks.

und dann nur weil ich ein wenig drüber gelesen habe double check:

  • wozu sind die Addressen und ein paar weitere globale nun in der Implementierung und nicht in der .h?

  • Aber eigentlich: warum keine member Variablen? zumindest die I2C Addressen würde sich anbieten. (Ja wird leider zu Lasten des SRAM gehen, weils der Compiler nicht gut wegoptimieren kann, aber manchmal kann man auch auf den Quellcode achten...)

Das ist gar nicht so einfach.....(meine ich)
Denn es gibt keine gemeinsame (pure abstrakte) BasisKlasse.
Weißt du eine schöne Lösung?

Ja, das kann Ärger machen!
z.B. wenn man auf einem ESP8266 alternative Pins für I2C nutzen möchte.
Oder wenn der UNO nicht nur Master, sondern auch Slave, sein soll.
Dummerweise findet sich das in vielen Libs, das Wire.begin()

Ok wenn ich die Wire aus dieser bibliothek entferne, und nur im Usersketch einbinde, muss ich diese auch aus der VL53L0X, und aus der (rudimentären) DS3231 entfernen. Aber wie manage ich dann in der Lib, wenn ich es dem User überlassen will, welche Wire er nutzen will, mir den unterschiedlichen Funktionsaufrufen? (die Tiny Wire kennt z.B. keine Funktion mit Namen 'Wire.write' , dort heisst das 'Wire.send' o.ä.

Der Tipp mit den mehrfachen Wire.begin() ist gut, das werde ich korrigieren.
Die Adressen und Globalen werde ich in die h setztn.

wegen den I2C-Adressen : die lib ist eigentlich auf die 0.96 128x64 i2c Displays mit der Adresse 0x3c fix eingestellt gewesen. Allerdings warf sie noch eine Warnung wegen einer unbenutzten Variablen 'adress', weil Ursprünglich wohl mal die i2c-Adresse beim Iniit übergeben wurde. das habe ich dann wieder angepasst , damit diese Warnung weg ist. Die EEPROM-Adresse habe ich auf die Standard 0x50 als Startwert, weil ich auf Meinem PCB bereits die Adressleitungen auf GND desetzt hatte. jedoch setze ich dann unsinnigerweise im Init die Adresse auf den Wert, die dort übergeben wird, das muss ich noch schöner machen.

Etwas zu lasten vom SRAM will ich gerade eben nicht machen, ich will ja möglichst wenig SRAM verbrauchen, um mehr für anderes frei zu haben.

Ich danke euch für Die Tipps und versuche , was ich da jetzt noch raushoolen kann.

Das kann ich dir zeigen. Zumindest, wie ich das abgehandelt habe.
Aber das ist nicht "schön" geworden!
Ich bin hungrig, nach einer schöneren Lösung.
Vielleicht fällt dir ja dazu noch was ein......

Das geht dann gar nicht.
Aber zum Glück gibts ja viele TinyWire Dinger, auch welche, wo es write und nicht send heißt.

CombieI2cEeprom.zip (14,3 KB)

ja, nur gibt es da dann auch wieder welche, di dafür wiederum den einen oder anderen prozessor nicht kennen, dann muss ich eben halt auch da wieder anpassen. Hatte da nämlich arge Probleme: habe viele Tiny Dinges ausprobiert, einige kannten den ATtiny167 nicht, andere wiederum hatten andere Funktions-Namen , wiederum eine andere wollte v^weigerte sich hartnäckig , mit der VL53L0X zusammen zu arbeiten, hätte dann also auch jene lib wieder anpassen müssen, hatte da eh schon probleme , eine zu finden, die ich auch noch in den ATtiny rein bekomme,und auch damit läuft. Die hat dan eigentlich den Ausschlag gegeben , die Wire einzusetzen, da sie für wir Wire geschrieben ist und damit auch gut läuft und eben auch mit der Wire-Version von Spence Konde, die dem ATtiny-Core beiliegt. darum habe ich dann eben beschlossen, alle libs für dieses Projekt, auf die Wire zu setzen. die vielen Wire-beginn in der minimal-lib waren da schon so drin, aber die habe ich jetzt enfernt.
Mir geht is momentan einfach darum, diejenigen libs, die ich jetzt in diesem Projekt benötige , soweit anzupassen, dass ich am ende alles problemlos in meinen Attiny167 reinbekomme. Das Projekt ist ein Trocken-Futter Dosier-Automat für meine Katze. (Oder für die Katz???)
Da kann ich bis zu drei Futter-Rationen / Tag programmieren, die dann in die Futterschale ausgegeben werden. Als Sensoren sind 2 Laser-Distanzmess-Sensoren (VL53L0X für den Futterstand im Reservoir und in der Futterschale vorhalnden, Ein Schrittmotor bewegt die Förderschnecke , dieser ist mit einem Index-Sensor sowie mit einem AntiBlockierSensor ausgestattet. Ein kleiner digital-Joystick (5 tasten) ermöglicht die Programierung, sowie auch die direkte (manuelle) Motor-Steuerung, sowie eine manuelle futter-Ausgabe. Eine Notstrom-Batterie sorgt dafür, dass eine Futterausgabe auch während eines Stromausfalls ausgeführt wird, Ein Piezo Buzzer gibt Alarm, wenn das Futter-Reservoir leer ist. Futterreserve, Zustand der Notstrom-Batterie, Futterausgabe-Zeiten, sowie ob grosse , od. kleine Ration werden auf dem 0.96" Oled im Standard-Bildschirm angezeigt, Ausserdem auch eine schwänzelnde Katze, als HeartBeat. Und natürlich die Aktuelle Uhrzeit. Datum wird weder ausgewertet noch angezeigt. Der Status der Notstrom-Batterie wird nur alle 30 Tage , oder natürlich beim ProgrammStart , aktualiert, da die Spannungs-Messung unter Last erfolgt. Die Automatische Umschaltung auf Notstrom erfolgt nur, wenn der DC-Stecker vom externen Netzteil in der Buchse steckt. Wenn das Gerät also zur Reinigung durch ausstöpseln des DC-Steckers vom netzeil getrennt wird, schaltet das Gerät ab. Wird nur das Netzteil aus der Steckdose gezogen oder der Strom fällt aus, wird auf Notstrom umgeschaltet. Dabei wird dann das Oled , in den Energiesparmode versetzt. der ATtiny bleibt jedoch normal am laufen. Als HeartBeat dient in diesem Fall eine (sehr helle Farbwechsel-LED die mit 200 - 250 mikroAmpere auskommt, und so auch am Tag noch immer sichtbar ist.
Das Gerät überwacht während der Futterausgabe auch, ob die Ration überhaupt platz in der Futterschale hat, um diese nicht zu überfüllen, falls die Katze mal etwas weniger isst.

nein auch nicht. Ich mach halt auch nur den #include <Wire.h> im Usersketch.

Einfach offenbar nicht.
Aber wenn jemand eine I2C Lib hat deren Interface kompatibel zur Wire.h ist dann hat er diese Option.
Ansonsten muss er sich halt einen Wraper um die Memberfunktionen machen.
Daher ist es imho besser, den Wire.h include nicht in der Library zu machen.

ich sehe da zum Beispiel in einer TinyWire ein

	uint8_t TinyTwi::write(uint8_t data){
		return send(data);
	}

also scheint es zum Teil solche alias Funktionen eh schon zu geben.

wenn du nicht benutzte Variabeln behalten willst, weil du sie später vieleicht doch noch mal ergänzt
schreib einfach einmal ein
(void)adress; // for future use
in der Methode, dann ist das Warning weg.

I2C hat nur Stream als gemeinsames Interface und das reicht nicht (das ist nur zum Einlesen). Das ist gerade das Problem.
Das ist riesiger Fehler in der Arduino-Software weil man damals nicht konsequenter war als nur Stream und Print zu bauen. Wenn man das von Anfang an so konzipiert hätte dass z.B. alle I2C oder Serial Klassen jeweils eine gemeinsame abstrakte Basisklasse haben, wäre das kein Problem.

Ok, Stream als Basis nehmen und sich dann darauf verlassen dass der Rest gleich heißt geht vielleicht theoretisch. Schön ist es aber nicht unbedingt. Allerdings erben die TinyWire Klassen nicht mal davon wenn ich das richtig sehe. Dadurch kann man dann Objekte verschiedener Klassen nicht über das gleiche Objekt ansprechen.

Wegen der Warnung : da wollte ich zuerst entweder umbauen, so dass ich die Adresse halt beim Init des Displays wieder übergebe, bin das dann aber falsch angegangen, so dass ich dann keine Warnung, sondern nen Error bekam. Hab dass dann vorerst mal so belaasen, dass er halt mit Warnung, aber wenigstens funktional kompilierte und mich um anderes gekümmert.
Das Prblem mit den TinyWires war ja, dass ich zwar auch die eine oder andere hatte, deren interface zwar zu Wire kompatibel war, jedoch liefen die dafür wiederum nicht mit dem ATtiny167, mit anderen ATtinys liefen die schon. jedoch benötigte ich Aufgrund der Grösse meines Projekts unbedingt einen ATTiny mit mehr als 8KB Flash, was ja der 167er bietet.
Immerhin umfasst das Display neben dem Mainscreen 5 Menuepages, die Energieversorgung muss überwacht werden, dann die 'Schaltuhr', der Joystick , Und natürlich auch messund des Futterstandes im Reservoir, und die Steuerung des Motors, ergibt halt alles Programm-Code, der der ja irgendwie in den Controller rein muss. Nun Gut dies sollte jetzt auch klappen, schon durch das auslagern des Zeichensatzes und der Icons/Symbole und Animationen in das I2C-EEProm hat mir gut 2,5KB gebracht. der ProgrammCode ist auch eigentlich schon fertig , jedoch fehlt dennoch eine Ausgabe, falss z.B. die Sicherung von der Motor-Versorgung durchbrennen sollte, oder der Antrieb so verklemmt sein, dass das Gerät, das Problem nicht automatisch gelöst bekommt. in diesen Fällen möchte ich optische und akustische Rückmeldung. Dazu muss ich den Programmcode eben jetzt noch erweitern. Jedoch hatte ich schlichtweg nicht mehr genügend Platz, um noch zusätzlichen Text oder Warn-Symbole /Icons im PROGMEM abzulegen. und ich will den Flash auch nicht bis aufs letzte Byte füllen.

Ach ja, ich habe natürlich auch während dem Schreiben meines Codes auch wieder dazu gelernt, und konnta dann das Problem mit der Warnung wegen der Variablen lösen. Inzwischen konnte ich heute bei meiner SSD1306-minimal_erom Lib wieder ein par Bytes einsparen, und das eine oder andere sauberer gestalten. So habe ich nun auch die I2C adresse für das EEPROM in der .h deklariert und auf Standard 0x50 gesetzt. dann hab ich die kleine Funktion 'setRomAddress' geschrieben, über die ich die Adresse im Bereich 0x50 bis 0x57 ändern kann. ich schaue noch, wie ich das mit den ZeichensatzAdressen für zusätzliche Zeichensätze eleganter gelöst bekomme, aber das krieg ich schon hin - denke ich.

nicht getestet aber so eine Wurst an sendCommands:

sendCommand(GOFi2cOLED_Display_Off_Cmd);    /*display off*/

  sendCommand(Set_Multiplex_Ratio_Cmd);    /*multiplex ratio*/
  sendCommand(0x3F);    /*duty = 1/64*/

  sendCommand(Set_Display_Offset_Cmd);    /*set display offset*/
  sendCommand(0x00);

  sendCommand(Set_Memory_Addressing_Mode_Cmd); 	//set addressing mode
  sendCommand(HORIZONTAL_MODE); 			//set horizontal addressing mode

  sendCommand(0xB0); 			//set page address
  sendCommand(0x00); 	//set column lower address
  sendCommand(0x10); 	//set column higher address

  sendCommand(0x40);    /*set display starconstructort line*/

  sendCommand(Set_Contrast_Cmd);    /*contract control*/
  sendCommand(0xcf);    /*128*/

  sendCommand(Segment_Remap_Cmd);    /*set segment remap*/

  sendCommand(COM_Output_Remap_Scan_Cmd);    /*Com scan direction*/

  sendCommand(GOFi2cOLED_Normal_Display_Cmd);    /*normal / reverse*/

  sendCommand(Set_Display_Clock_Divide_Ratio_Cmd);    /*set osc division*/
  sendCommand(0x80);

  sendCommand(Set_Precharge_Period_Cmd);    /*set pre-charge period*/
  sendCommand(0xf1);

  sendCommand(Set_COM_Pins_Hardware_Config_Cmd);    /*set COM pins*/
  sendCommand(0x12);

  sendCommand(Set_VCOMH_Deselect_Level_Cmd);    /*set vcomh*/
  sendCommand(0x30);

  sendCommand(Deactivate_Scroll_Cmd);

  sendCommand(Charge_Pump_Setting_Cmd);    /*set charge pump enable*/
  sendCommand(Charge_Pump_Enable_Cmd);

  sendCommand(GOFi2cOLED_Display_On_Cmd);    /*display ON*/

evtl ein Array in Progmem und dann in einer Schleife abarbeiten?

müsste man ausprobieren, ob sich da ne ersparnis im Flash ergibt, es sind ja mehrere Funktionen, die verschiedene Commands nutzen. Ich sehe es mir auf jedenfall an, Inzwischen ist der Sketch immerhin von 95% auf 80 % Flash verbrauch gesunken. Also für dieses Projekt komme ich jetzt auf jeden Fall mit dem Flash klar. Sollten wirklich alle stricke reissen, kann ich die Motor-Steuerung inkl. der dazu benötigten Sensorik welche zur Erkennung der blockierten Förderschnecke dient, Sowie der Status-Rückmeldung des Ausgabeverschlusses, in einen Attiny 84 auslagern. Dann bekommt der Motor nur noch ein Power on, Mache eine Umdrehung, und ein Richtungssignal. Die rückmeldung erfolgt dann mittels einer Busy-Leitung. Dies erspart dann nochmals etwas Flash.
Das PCB ist jedenfalls vorsichtshalber für beide Varianten ausgestattet.
Aber wenn ich alles in den ATTiny 167 rein bekomme, umso besser.
Ich habe meine Anfänge im Programieren auf einem ZX81 OHNE Zusatzspeicher (16Kb Ram Modul kostete damals um die 300 Franken) Und da hat man mit allen mitteln versucht, möglichst viel Programm-Funktion in 1KB reinzuquetschen. und irgendwie ist da bei mir wohl etwas zurück geblieben :rofl:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.