Hy
I am trying 2 build a controller for my parking heater with a attiny85 (digispark).
So far I got a encoder switch a i2c display and sensor working just fine, but now the flash memory is full.
I know about the 2 options to delete the bootloader or simply take a bigger chip (arduino nano already ordered to use as new controller or programmer for the 85 or both)
I am also thinking about writing parts of my program in assembler, but i am using the libraries TinyWire and LiquidChristal_attiny and scince my code contains mainly calls to these libraries and not much other code, i fear that writing my code in assembler wont help much but i realy would need to rewrite the libraries. Is this correct or do you have any other ideas?
Thx
Here the code
#include <avr/io.h> #include <util/delay.h> #include <TinyWireM.h> #include <LiquidCrystal_attiny.h> #define LCD_ADDR 0x27 #define LCD_WIDTH 16 #define LCD_HEIGHT 2 #define TEMP_ADDR 0x40 #define ENC_A 1 #define ENC_B 4 #define OUT_1 3 #define OUT_2 5 #define delay_time 160 //in sec #define delay_time_on 5 //in sec #define menu_len 6 LiquidCrystal_I2C lcd(LCD_ADDR, LCD_WIDTH, LCD_HEIGHT); // set address & 16 chars / 2 lines volatile int8_t enc_old = 2; //encoder state memory volatile int8_t Enc_turn = 0; //how often encoder has been turned volatile int8_t Enc_sw = 0; //if encoder has been pushed int16_t temp=999; //ist-temp*10 uint8_t temp_retry=0,temp_state=0; int16_t t_lim = 150, t_on=60,t_off=60; //soll-temp*10 uint8_t t_hyst=10; uint8_t state=0; //0=ports off, 1=1 port on, 2= 2 ports on volatile unsigned long t_activ=millis(); //time of last encoder state change int8_t pos_m=1; char* Menu[menu_len] = {"Exit ","Temp ", "OnTime ", "OffTime", "Repeat ", "Hyst. "}; uint8_t m_state[4]={1,0,0,0}; uint8_t i2c_w8(uint8_t addr,uint8_t data) //send i2c command { TinyWireM.beginTransmission(addr); TinyWireM.send(data); uint8_t r = TinyWireM.endTransmission(); return r; }; static inline void initTimer(void) { TCCR1 |= (1 << CTC1); // clear timer on compare match TCCR1 |= (1 << CS13) | (1 << CS12) | (1 << CS11) | (1 << CS10); //clock prescaler 8192 OCR1C = 1; // compare match value TIMSK |= (1 << OCIE1A); // enable compare match interrupt sei(); }; ISR(TIMER1_COMPA_vect) //timed interrupt to read encoder state { enc_old = (enc_old & 0b110000) | (enc_old & 0b11) << 2 | ((PINB >> ENC_A & 1) << 1) | (PINB >> ENC_B & 1); if (enc_old == 0b001101) { Enc_turn++; enc_old |= 0b010000; t_activ=millis(); } else if (enc_old == 0b001110 ) { Enc_turn--; enc_old |= 0b010000; t_activ=millis(); } else if (enc_old == 0b001100) {Enc_sw = 1;t_activ=millis();} else if ((enc_old & 0b110011) == 0b010000) enc_old &= 0b001111; }; void setup(void) { //TinyWireM.begin(); lcd.init(); lcd.backlight(); i2c_w8(TEMP_ADDR,0xFE); //sensor reset DDRB|=1<<ENC_A+1<<ENC_B; PORTB|=1<<ENC_A+1<<ENC_B; initTimer(); }; void show_val(int16_t val,uint8_t dec,char* unit) //show int16 as float { uint8_t pos; int8_t rval; if (dec) { val=val/pow(10,dec); rval=val%(int16_t)pow(10,dec); }; if(val>99) pos=0; else if (val>9) pos=1; else pos=2; if (val<0) { pos--; rval=-rval;}; while(pos--) lcd.print(" "); lcd.print(val); if (dec) { lcd.print("."); lcd.print(rval); }; lcd.print(unit); }; uint16_t set_val(int16_t val,uint8_t dec, uint8_t step,char* unit) //show and adjust a numerical value with encoder { while (true) { lcd.setCursor(4,1); show_val(val,dec,unit); if (Enc_sw) { Enc_sw=0; return val; } else { val+=step*Enc_turn; Enc_turn=0; } delay(100); }; } inline uint8_t measure() //read temperature sensor (call repeatedly until result) { uint8_t s; temp_retry++; if (temp_retry%20==0) { i2c_w8(TEMP_ADDR,0xFE); //reset temp_state=0;}; if (temp_state==0) { i2c_w8(TEMP_ADDR,0xF3); //start measurement temp_state=1;} else temp_state=TinyWireM.requestFrom(TEMP_ADDR,2); //read temperature if(!temp_state) { uint16_t hi=TinyWireM.receive()<<8; hi+=TinyWireM.receive(); temp=(int16_t)(0.026813*hi-468.5); temp_retry=0; return 0; } else if(temp_retry>60) { temp=-999; temp_state=0; temp_retry=0; return 2;}; return 1; }; void show_tt() //display actual temperature, set temperature and timing { lcd.setCursor(0,0); lcd.print((int)state); lcd.print(" T"); show_val(temp,1,""); if (m_state[0]) { lcd.print(" >"); show_val(t_lim,1,"C");}; if (m_state[1]) { lcd.setCursor(2,1); lcd.print("t1"); show_val(t_on,0,"m");}; if (m_state[2]) { lcd.setCursor(2,1); lcd.print("t2"); show_val(t_on,0,"m");}; }; inline void set_state() //swich state/ports according to temperature { if (temp <= t_lim) state=1; if (temp<=t_lim-t_hyst) state=2; else if (temp>=t_lim+t_hyst) state=0; //PORTB|=(PORTMASK&(state|state<<1)); } void loop() { measure(); show_tt(); set_state(); if(Enc_sw or Enc_turn) //if user input { Enc_sw=0; if (pos_m<0) //if display was off, display on {lcd.init(); lcd.backlight(); pos_m=0; } else if(Enc_turn) //if encoder turned adjust temperatuer setting { t_lim+=5*Enc_turn; Enc_turn=0; } else //if encoder pushed show menu { lcd.clear(); while (1) { lcd.setCursor(3, 0); lcd.print(Menu[pos_m]); //show menu item in line 1 lcd.setCursor(13, 0); if(pos_m>0 && pos_m<5) { if(m_state[pos_m-1] && pos_m<5) lcd.print(" On"); //show state of menu item else lcd.print("Off");} else lcd.print(" "); lcd.setCursor(3, 1); if(pos_m<menu_len-1) lcd.print(Menu[pos_m+1]); //show menu item of line 2 else lcd.print(" "); delay(100); if (Enc_sw) //if pushbutton execute menuitem { Enc_sw=0; lcd.clear(); if(pos_m==0) break; //quit menu else if (pos_m<5) m_state[pos_m-1]^=1; //toggle options (temp mode, time mode,...) else if(pos_m==5) { lcd.setCursor(13, 0); //adjust hysteresis set_val(t_hyst,1,1,"C"); if(t_hyst<0) t_hyst=-t_hyst;} Enc_turn=pos_m; lcd.clear(); } else //if Enc_turn is out of limits (number of menu itims) { pos_m=Enc_turn; if (pos_m<0) pos_m=0; else if (pos_m>menu_len-1) pos_m=menu_len-1; } Enc_turn=pos_m; if(millis()-t_activ>5000) break; // }; lcd.clear(); }; }; delay(100); if(millis()-t_activ>20000) //backlight off if inactive { lcd.noBacklight(); lcd.init(); pos_m=-1; }; };