|  |  | @ -14,18 +14,38 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "modbus.h" |  |  |  | #include "modbus.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "menu.h" |  |  |  | #include "menu.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "adc.h" |  |  |  | #include "adc.h" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include "pid.h" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #define COIL1 1<<1 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #define COIL2 1<<0 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #define COIL3 1<<2 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #define COIL4 1<<3 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | volatile uint16_t holdingRegisters[10]; |  |  |  | volatile uint16_t holdingRegisters[10]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | volatile uint16_t temp_values[4]; |  |  |  | volatile uint16_t temp_values[4]; | 
			
		
	
		
		
			
				
					
					|  |  |  | volatile uint16_t temp_setpoints[4]; |  |  |  | volatile uint16_t temp_setpoints[4]; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | volatile uint16_t output; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | volatile struct pid controller; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | volatile uint32_t duty[3]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void modbusGet(void) { |  |  |  | void modbusGet(void) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	if (modbusGetBusState() & (1<<ReceiveCompleted)) |  |  |  | 	if (modbusGetBusState() & (1<<ReceiveCompleted)) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  |         switch(rxbuffer[1]) { |  |  |  |         switch(rxbuffer[1]) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             case fcReadHoldingRegisters: |  |  |  |             case fcReadHoldingRegisters: | 
			
		
	
		
		
			
				
					
					|  |  |  |                 holdingRegisters[0] = menu_state; |  |  |  |                 holdingRegisters[0] = duty[0]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 holdingRegisters[1] = duty[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 holdingRegisters[2] = duty[2]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 holdingRegisters[3] = temp_values[0]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 holdingRegisters[4] = temp_values[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 holdingRegisters[5] = temp_values[2]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 modbusExchangeRegisters(holdingRegisters,0,10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             case fcPresetSingleRegister: |  |  |  |             case fcPresetSingleRegister: | 
			
		
	
		
		
			
				
					
					|  |  |  |             case fcPresetMultipleRegisters: |  |  |  |             case fcPresetMultipleRegisters: | 
			
		
	
		
		
			
				
					
					|  |  |  |                 modbusExchangeRegisters(holdingRegisters,0,4); |  |  |  |                 modbusExchangeRegisters(holdingRegisters,0,4); | 
			
		
	
	
		
		
			
				
					|  |  | @ -38,7 +58,7 @@ void modbusGet(void) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void do_buttons(){ |  |  |  | void read_buttons(){ | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     i2c_start(0x71); |  |  |  |     i2c_start(0x71); | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint8_t buttons = i2c_readNak(); |  |  |  |     uint8_t buttons = i2c_readNak(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     i2c_stop(); |  |  |  |     i2c_stop(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -54,62 +74,143 @@ void do_buttons(){ | 
			
		
	
		
		
			
				
					
					|  |  |  |         set_item(4); |  |  |  |         set_item(4); | 
			
		
	
		
		
			
				
					
					|  |  |  |     else if(buttons & (1 << 4)) |  |  |  |     else if(buttons & (1 << 4)) | 
			
		
	
		
		
			
				
					
					|  |  |  |         set_item(5); |  |  |  |         set_item(5); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     else if((buttons & (1 << 5)) == 0) // inverted logic on this one
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         set_item(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | int main(void) |  |  |  | int main(void) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     DDRB |= 0x0F;       // output coils
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     DDRD |= (1 << 4);   // board LED
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	i2c_init(); |  |  |  | 	i2c_init(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	lcd_init(); |  |  |  | 	lcd_init(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     adc_init(); |  |  |  |     adc_init(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     enc_init(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	lcd_clear(); |  |  |  |     init_pid(&controller, 1, 0.05, 0); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     sei(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     modbusSetAddress(1); |  |  |  |     modbusSetAddress(1); | 
			
		
	
		
		
			
				
					
					|  |  |  |     modbusInit(); |  |  |  |     modbusInit(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     TCCR0B|=(1<<CS01); //prescaler 8
 |  |  |  |     //modbus timer
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     TCCR0B|=(1<<CS01); | 
			
		
	
		
		
			
				
					
					|  |  |  | 	TIMSK0|=(1<<TOIE0); |  |  |  | 	TIMSK0|=(1<<TOIE0); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     PORTD |= (1<<6) | (1 << 7); |  |  |  |     // timer for regulator
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     PCICR |= (1<<PCIE2); |  |  |  |     TCCR1B|=(1<<CS12) | (1<<CS10); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     PCMSK2 |= (1<<PCINT23); |  |  |  | 	TIMSK1|=(1<<TOIE1)|(1<<OCIE1A); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     sei(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	lcd_clear(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     draw_menu(); |  |  |  |     draw_menu(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint16_t x = 0; |  |  |  |     uint16_t x = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	while(1){ |  |  |  | 	while(1){ | 
			
		
	
		
		
			
				
					
					|  |  |  |         modbusGet(); |  |  |  |         modbusGet(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         do_buttons(); |  |  |  |         read_buttons(); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         //blink cursor
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if(x==0){ |  |  |  |         if(x==0){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         //}
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ////write values
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         //if(x % 2048 == 0){
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             lcd_cursor(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |             write_temps(); |  |  |  |             write_temps(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             write_setpoints(); |  |  |  |             write_setpoints(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             write_motor(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             update_cursor(); |  |  |  |             update_cursor(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         x++; |  |  |  |         x++; | 
			
		
	
		
		
			
				
					
					|  |  |  |         if(x>=2024) |  |  |  |         if(x >= 1024) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             x=0; |  |  |  |             x=0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | ISR(PCINT2_vect){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     encoder_isr(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ISR(TIMER0_OVF_vect) { //this ISR is called 9765.625 times per second
 |  |  |  | ISR(TIMER0_OVF_vect) { //this ISR is called 9765.625 times per second
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	modbusTickTimer(); |  |  |  | 	modbusTickTimer(); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ISR(PCINT2_vect){ |  |  |  | ISR(TIMER1_COMPA_vect) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //TODO good quadrature reading code
 |  |  |  |     /* turn off outputs */ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if((PIND & (1<<7)) && (menu_state >= 1) && (menu_state <= 3)){ |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if(PIND & (1<<6)) |  |  |  |     if(OCR1A >= duty[0]){ | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             temp_setpoints[menu_state-1]--; |  |  |  |         PORTB &= ~(COIL1); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         else |  |  |  |         PORTD &= ~(1 << 4); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             temp_setpoints[menu_state-1]++; |  |  |  |     } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(OCR1A >= duty[1]) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         PORTB &= ~(COIL2); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(OCR1A >= duty[2]) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         PORTB &= ~(COIL3); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     uint16_t new_ocr = 0xFFFE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for(uint8_t i = 0; i < 3; i++){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if((duty[i] > OCR1A) && (duty[i] < new_ocr)) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             new_ocr = duty[i]; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     OCR1A = new_ocr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     //if(PIND & (1<<7))
 |  |  |  |     //uint16_t tmp1 = duty[0];
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //    if(PIND & (1<<6)){
 |  |  |  |     //uint16_t tmp2;
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //        if(temp_setpoints[menu_state] > 0)
 |  |  |  |     //for(uint8_t i = 0; i < 3; i++){
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //    }
 |  |  |  |     //    if(duty[i] < tmp1 && duty[i] > OCR1A)
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //    else{
 |  |  |  |     //        tmp2 = duty[i];
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //        if(temp_setpoints[menu_state] < 300)
 |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     //}
 |  |  |  |     //}
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     //OCR1A = tmp2;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | ISR(TIMER1_OVF_vect) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     int16_t tmp_pid = pid_step(&controller, 1, temp_setpoints[0] - temp_values[0]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(tmp_pid>=0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         output = tmp_pid; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     else | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         output = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(output >= 128){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         output = 128; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         duty[0]=0xFFFE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     else if(output >= 1){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         uint32_t tmp = output * 512; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         duty[0] = tmp; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     else | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         duty[0]=0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     duty[1] = duty[0] / 100 * temp_setpoints[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     duty[2] = duty[0] / 100 * temp_setpoints[2]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for(uint8_t i = 0; i < 3; i++){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if(duty[i] >= 0xFFFE) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             duty[i] = 0xFFFE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     OCR1A = 0xFFFE; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for(uint8_t i = 0; i < 3; i++){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if(duty[i] < OCR1A && duty[i] >= (uint16_t)1000) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             OCR1A = duty[i]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(duty[0] >= 1000){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         PORTB |= COIL1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         PORTD |= 1<<4; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(duty[1] >= 1000) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         PORTB |= COIL2; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if(duty[2] >= 1000) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         PORTB |= COIL3; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |