/*! * Init Display */ void display_init(void){ shift_init(); DISPLAY_DDR |= DISPLAY_OUT; // Ausgänge DISPLAY_DDR &= ~DISPLAY_IN; // Eingänge delay(30); // Display steht erst 10ms nach dem Booten bereit // Register in 8-Bit-Modus 3x Übertragen, dazwischen warten shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY); DISPLAY_PORT= DPC; delay(5); shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY); DISPLAY_PORT= DPC; delay(5); shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY); DISPLAY_PORT= DPC; delay(5); display_cmd(0x0f); //Display On, Cursor On, Cursor Blink display_cmd(DISPLAY_CLEAR); // Display l�schen, Cursor Home display_data('i'); }
void noinline hd44780_output_4bit(uint8_t rs, uint8_t nibble, uint8_t en) { uint8_t data = 0; //Soll ins Seuer oder Datenregister geschrieben werden? if (rs) data |= (1 << LCD_RS_PIN); #ifdef HD44780_BACKLIGHT_SUPPORT #ifdef HD44780_BACKLIGHT_INV if (hd44780_backlight_state == 0) data |= (1 << LCD_LIGHT_PIN); #else if (hd44780_backlight_state) data |= (1 << LCD_LIGHT_PIN); #endif #endif data |= (nibble & 0x0f) << 3; //Write Nibble //Schreiben an das LCD shift_data_out(data); /* toggle EN */ hd44780_clock_write(1); }
/*! * Schreibt ein Zeichen auf das Display * @param data Das Zeichen */ void display_data(const char data) { /* Zeichen aus data in den Displayspeicher schreiben */ shift_data_out((BK_U8B) data, SHIFT_LATCH, SHIFT_REGISTER_DISPLAY | DISPLAY_RS); /* 47 us warten */ waitus(47); DISPLAY_PORT = DPC; // Alles zurueck setzen ==> Fallende Flanke von Enable }
/*! * Übertrage Kommando an das Display * @param cmd Kommando */ void display_cmd(uint8 cmd){ //ein Kommando cmd an das Display senden uint8 i; shift_data_out(cmd,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY); // Enable muss für mind. 450 ns High bleiben, bevor es fallen darf! // ==> Also mind. 8 Zyklen warten for (i=0; i<100; i++){ asm("nop"); } DISPLAY_PORT=DPC; // Alles zurück setzen ==> Fallende Flanke von Enable }
/*! * Ein Zeichen auf das Display schreiben * @param data Das Zeichen */ void display_data(char data){ //ein Zeichen aus data in den Displayspeicher schreiben uint8 i; shift_data_out(data,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY|DISPLAY_RS); // Enable muss für mind. 450 ns High bleiben, bevor es fallen darf! // ==> Also mind. 8 Zyklen warten for (i=0; i<120; i++){ asm("nop"); } DISPLAY_PORT=DPC; // Alles zurück setzen ==> Fallende Flanke von Enable }
/*! * Uebertraegt ein Kommando an das Display * @param cmd Das Kommando */ void display_cmd(BK_U8B cmd) { /* Kommando cmd an das Display senden */ shift_data_out(cmd, SHIFT_LATCH, SHIFT_REGISTER_DISPLAY); /* 47 us warten */ waitus(47); DISPLAY_PORT = DPC; // Alles zurueck setzen ==> Fallende Flanke von Enable if (cmd == DISPLAY_CLEAR) { /* 1.52 ms warten */ waitus(1520); } }
void hd44780_backlight(uint8_t state) { uint8_t data = 0; hd44780_backlight_state = state; #ifdef HD44780_BACKLIGHT_INV if (hd44780_backlight_state == 0) data |= (1 << LCD_LIGHT_PIN); #else if (hd44780_backlight_state) data |= (1 << LCD_LIGHT_PIN); #endif shift_data_out(data); }
/*! * Initialisiert das Display */ void display_init(void) { commandMQ = msgQueueAdd(); dataMQ = msgQueueAdd(); shift_init(); DISPLAY_DDR |= DISPLAY_OUT; // Ausgaenge DISPLAY_DDR = (BK_U8B) (DISPLAY_DDR & ~DISPLAY_IN); // Eingaenge _delay_ms(12); // Display steht erst 10ms nach dem Booten bereit hier kann nicht die ctbotKernel wait funktion genutzt werden da die interrupts erst später aktiviert werden und somit die wait funktion noch nicht funktioniert /* Register in 8-Bit-Modus 3x uebertragen, dazwischen warten */ BK_U8B i; for (i = 3; i > 0; --i) { shift_data_out(0x38, SHIFT_LATCH, SHIFT_REGISTER_DISPLAY); DISPLAY_PORT = DPC; _delay_ms(5); } display_cmd(DISPLAY_MODE); // Display an und Cursor-Modus setzen display_cmd(DISPLAY_CLEAR); // Display loeschen, Cursor Home }
void noinline hd44780_hw_init(void) { uint8_t data = 0; CTRL_OUTPUT(); PIN_CLEAR(HD44780_SER_CLK); PIN_CLEAR(HD44780_SER_EN1); PIN_CLEAR(HD44780_SER_D); DATA_OUTPUT(); #ifdef HD44780_BACKLIGHT_SUPPORT #ifdef HD44780_BACKLIGHT_INV if (hd44780_backlight_state == 0) data |= (1 << LCD_LIGHT_PIN); #else if (hd44780_backlight_state) data |= (1 << LCD_LIGHT_PIN); #endif #endif shift_data_out(data); }
/*! * Schiebt Daten durch eines der drei 74HC595 Schieberegister * vereinfachte Version, braucht kein shift_clear() * geht NICHT für das Shift-register, an dem das Display-hängt!!! * @param data Das Datenbyte * @param latch_data der Pin an dem der Daten-latch-Pin des Registers (PIN 11) hängt */ void shift_data(uint8_t data, uint8_t latch_data){ shift_data_out(data, latch_data, SHIFT_LATCH); shift_clear(); }
void main(void) { int i=0; // Loop Variable timeout_ctr = 0 ; //############################ Initialisation ###############################// // _SOURCE_ DeviceInit(); // DeviceInit.c InitGpio(); // GpioInit.c InitPieVectTable(); // PieVect.c InitPieCtrl(); // PieCtrl.c InitSci(); // Serial.c init_lcd_menu(); // LcdMenu.c lcd_init(); // LcdDriver.c SineRefInit(); // SineRefInit.c AdcInit(); // AdcInit.c PwmInit(); // PwmInit.c State.all = 0; State.bit.Start = 1; PeripheralEn.bit.Buttons= 1; // Allow button checks EnableInterrupts(); // PieCtrl.c DisableInverter(); // Ensure inverter is disabled on start-up lcd_position(0x5,0x0); lcd_puts("Kingfisher"); // Print introductory message on top line lcd_position(0x0,0x1); // Start Cursor From First Line lcd_puts(" Hydro Controller "); // Print introductory message on bottom line asm(" CLRC INTM, DBGM"); // Enable global interrupts and real-time debug CpuTimer0Regs.PRD.all = COUNTER0_PRD; // Initialise CPU timer0 CpuTimer1Regs.PRD.all = COUNTER1_PRD; // Initialise CPU timer0 //############################# Polling Loop ################################// while(1) { //#######################################################################// // STATES // //#######################################################################// // //############################ START STATE ##############################// if(State.bit.Start) { asm("NOP"); } //######################### EXCITATION STATE ############################// if (State.bit.Excitation) { data_out.bit.led_ctrl_green = 1; data_out.bit.led_ctrl_red = 0; if ( (AdcSignal.V_HVDC < 50) && (AdcSignal.Shaft_Velocity > 2000) && !(State.bit.Fault) ) { // PeripheralEn.bit.Buttons= 0; timeout_ctr++; if (timeout_ctr > 3) { State.all = 0; State.bit.Fault = 1; timeout_ctr = 0; } else { data_out.bit.startup = 1; shift_data_out(); if (CpuTimer0Regs.TCR.bit.TIF == 1) { for (i=1;i<=2;i++) // wait 2 seconds { CpuTimer0Regs.TCR.bit.TIF = 1; // Clear flag while(!CpuTimer0Regs.TCR.bit.TIF); } } data_out.bit.startup = 0; shift_data_out(); if (CpuTimer0Regs.TCR.bit.TIF == 1) { for(i=1;i<=3;i++) // wait 3 seconds { CpuTimer0Regs.TCR.bit.TIF = 1; // Clear flag while(!CpuTimer0Regs.TCR.bit.TIF); } } } } else if ( (AdcSignal.V_HVDC >= 50) && (AdcSignal.V_HVDC < 250) ) { timeout_ctr = 0; State.all = 0; State.bit.Excited = 1; // Perhaps change LCD Screen to message saying "Slowly increase turbine speed to increase voltage." } else if ( (AdcSignal.V_HVDC > 250) ) { timeout_ctr = 0; // Resets the timeout counter for excitation State.all = 0; State.bit.StartupSequence = 1; } } //############################ EXCITED STATE ############################// if (State.bit.Excited) { if (AdcSignal.V_HVDC > 250) { timeout_ctr = 0; // Resets the timeout counter for excitation State.all = 0; State.bit.StartupSequence = 1; } else { // !!!!! ADD SOME CODE FOR THIS CONDITION !!!!! } } //############################# FAULT STATE #############################// if (State.bit.Fault) { if (PeripheralEn.bit.Inverter) { DisableInverter(); data_out.bit.led_dump1 = 0; data_out.bit.led_dump2 = 0; data_out.bit.led_inverter = 0; data_out.bit.led_update = 0; } data_out.bit.protect_trig = 1; data_out.bit.led_ctrl_green = 0; data_out.bit.led_ctrl_red = 1; if ( !(LED_Fault_Ctr++ % 16384) ) { data_out.bit.led_dump1 = ~(data_out.bit.led_dump1); data_out.bit.led_dump2 = ~(data_out.bit.led_dump2); data_out.bit.led_inverter = ~(data_out.bit.led_inverter); data_out.bit.led_update = ~(data_out.bit.led_update); } } //########################### DC STABLE STATE ###########################// if (State.bit.DcStable) { if ( !(PeripheralEn.bit.Inverter) ) EnableInverter(); data_out.bit.led_ctrl_green = 1; data_out.bit.led_ctrl_red = 0; } //############################## TEST STATE #############################// if (State.bit.Test) { } //########################### TURNED OFF STATE ##########################// if (State.bit.TurnOff) { data_out.bit.led_ctrl_green = 0; data_out.bit.led_ctrl_red = 0; data_out.bit.led_dump1 = 0; data_out.bit.led_dump2 = 0; data_out.bit.led_inverter = 0; data_out.bit.led_update = 0; } //#######################################################################// // FLAGS // //#######################################################################// // //######################## SCREEN UPDATE FLAG #######################// if (flag_bc) { menu_update_lcd(); flag_bc = 0; } asm(" nop"); //########################### READ IN DATA FLAG #########################// if (flag.bit.DataIN) { shift_data_in(); check_buttons(); flag.bit.DataIN = 0; } //########################## SEND OUT DATA FLAG #########################// if (flag.bit.DataOUT) { shift_data_out(); flag.bit.DataOUT = 0; } //######################## HVDC VOLTAGE REGULATION ######################// if (flag.bit.V_HVDC) { if ( !(State.bit.TurnOff) && !(State.bit.Fault) ) { V_DcError = V_DC_REF - AdcSignal.V_HVDC; // Calculate the DC error from the reference DutyError = 0.75*K_DC*V_DcError + 0.25*DutyError; // Modify the dump load duty cycle with respect to the DC error if (V_DcError > 0) // If the DC voltage is less than the reference, dump no power { EPwm3Regs.CMPA.half.CMPA= 0; EPwm3Regs.CMPB = 0; } else if (DutyError > DUMP1_DUTY_MAX) { DutyFeedback = 1.0*(DUMP1_DUTY_MAX)*DUMP_PRD; EPwm3Regs.CMPA.half.CMPA= DutyFeedback; DutyFeedback = 1.0*(DutyError - DUMP1_DUTY_MAX)*DUMP_PRD; EPwm3Regs.CMPB = DutyFeedback; } else { DutyFeedback = 1.0*(DutyError)*DUMP_PRD; EPwm3Regs.CMPA.half.CMPA= DutyFeedback; EPwm3Regs.CMPB = 0; } }else // If there is a fault or the system is off, dump all power { EPwm3Regs.CMPA.half.CMPA = (DUMP1_DUTY_MAX)*DUMP_PRD; // Dump all power! EPwm3Regs.CMPB = DUMP_PRD; // Dump all power! } flag.bit.V_HVDC = 0; // Reset the flag } //###################### SHAFT VELOCITY MEASUREMENT #####################// if (ShaftVelocCtr >= 1000) // Updates the measured velocity every 1000*(1/EPWM8) = 0.5s { AdcSignal.Shaft_Velocity = shaftspeedtest; //0.8*(ShaftPulseCtr/0.5)*60 + 0.2*AdcSignal.Shaft_Velocity; // Where 1 pulse = 1 rotation ShaftPulseCtr = 0; // { Reset counters ShaftVelocCtr = 0; // { } //################### OUTPUT AC VOLTAGE FREQUENCY MEASURE ################// if (V_AcOutPrdCtr >= 10) { AdcSignal.V_AcOut_Freq = (SYSCLK/ADC_SAMP_PRD+1)*(V_AcOutPrdCtr/FreqOutDivCtr); // Approximate frequency over at least 10 periods AcOutFreqError = AC_OUT_FREQ - AdcSignal.V_AcOut_Freq; // Find frequency error V_AcOutReqFreq = V_AcOutReqFreq + 0.05*AcOutFreqError; // Frequency feedback loop sinGen.freq = V_AcOutReqFreq*(BIT31)*(2*BIT32*INVERTER_PWM_PRD)*(1/(sinGen.step_max*SYSCLK)); // Alter reference sine wave frequency V_AcOutPrdCtr = 0 ; // } FreqOutDivCtr = 0 ; // } Reset counters } //####################### INVERTER CONTROL #######################// if (flag.bit.Inverter) { /* BROKEN InverterMaxDuty = V_AC_OUT_REF*(1.0/(AdcSignal.V_HVDC)); // Find the maximum duty cycle necessary to create Vacoutpeak=325V DutyScaleMax = (BIT16*InverterMaxDuty-BIT15)*30.51850948e-6; // 30.51850948e-6 = 1/(BIT15-1) if ( !(State.bit.InvSoftStart) ) { DutyScaleError = DutyScaleMax - DutyScale; DutyScale = DutyScale + 0.01*DutyScaleError; if (DutyScale < 0.2) { DutyScale = 0.2; ADD SOME CODE IN CASE IT IS DANGEROUS TO GO BELOW 0.2 } } */ // ----- Toggle the onboard LED to show inverter control is active if (GPIO34_count >= 4000) // toggle_time = GPIO34_count_limit/fpwm { GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // Toggle the pin GPIO34_count = 0; // Reset the count } flag.bit.Inverter = 0; } //################### INPUT AC VOLTAGE FREQUENCY MEASURE ################// if (V_AcInPrdCtr >= 10) { AdcSignal.V_AcIn_Freq = 0.8*((SYSCLK/ADC_SAMP_PRD+1)*(V_AcInPrdCtr/FreqInDivCtr)) + 0.2*(AdcSignal.V_AcIn_Freq); // Approximate frequency over at least 10 periods genSlip = 100*((AdcSignal.V_AcIn_Freq*60) - (AdcSignal.Shaft_Velocity))/(AdcSignal.V_AcIn_Freq*60); // Calculates slip: s= 100%*((ns-nr)/ns) V_AcInPrdCtr = 0 ; // } FreqInDivCtr = 0 ; // } Reset counters } /* if(SendADCResult) { SendADCResult = 0; SerialSendStr("Voltage: "); SerialSendInt((int)V_DC_measured); SerialSendStr(" PWM1: "); SerialSendInt((int)(EPwm3Regs.CMPA.half.CMPA*100.0/(DUMP_PRD*1.0))); SerialSendCR(); SerialSendStr(" PWM2: "); SerialSendInt((int)((EPwm3Regs.CMPB*100.0)/(DUMP_PRD*1.0))); SerialSendCR(); }*/ } }