📄 ddcp.c
字号:
/*********************************************
* vim: set sw=8 ts=8 si :
* Author: Guido Socher, Copyright: GPL
* This is the main program for the digital dc power supply
*
* See http://www.tuxgraphics.org/electronics/
*
* Chip type : ATMEGA8
* Clock frequency : Internal clock 4 Mhz
*********************************************/
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include "lcd.h"
#include "dac.h"
#include "kbd.h"
#include "analog.h"
#include "avr_compat.h"
#include "hardware_settings.h"
#include <stdlib.h> // atoi
#include <string.h>
#include <avr/eeprom.h>
static int set_val[2];
// the set values but converted to ADC steps
static int set_val_adcUnits[2];
void delay_ms(unsigned char ms)
/* delay for a minimum of <ms> */
/* with a 4Mhz clock */
{
uint8_t inner,inner1;
while (ms) {
inner = 200;
while (inner) {
inner--;
inner1 = 70;
while (inner1) {
inner1--;
}
}
ms--;
}
}
// Convert a integer which is representing a float into a string.
// decimalpoint_pos sets the decimal point after 2 pos: e.g 74 becomes "0.74"
// The integer may not be larger than 10000.
// The integer must be a positive number.
// spacepadd can be used to add a leading speace if number is less than 10
static void int_to_ascii(int inum,char *outbuf,signed char decimalpoint_pos,signed char spacepadd){
signed char i,j;
char chbuf[8];
j=0;
while(inum>9 && j<7){
// zero is ascii 48:
chbuf[j]=(char)48+ inum-((inum/10)*10);
inum=inum/10;
j++;
if(decimalpoint_pos==j){
chbuf[j]='.';
j++;
}
}
chbuf[j]=(char)48+inum; // most significant digit
decimalpoint_pos--;
while(j<decimalpoint_pos){
j++;
chbuf[j]='0';
}
if (spacepadd && j > (decimalpoint_pos+2)){
// no leading space padding needed
spacepadd=0;
}
if(decimalpoint_pos==j){
j++;
chbuf[j]='.';
j++;
chbuf[j]='0'; // leading zero
}
if (spacepadd){
j++;
chbuf[j]=' '; // leading space padding: "9.50" becomes " 9.50"
}
// now reverse the order
i=0;
while(j>=0){
outbuf[i]=chbuf[j];
j--;
i++;
}
outbuf[i]='\0';
}
// convert voltage values to adc values, disp=10 is 1.0V
static int disp_u_to_adc(int disp){
return((int)(disp * 102.3) / (ADC_REF * U_DIVIDER));
}
// calculate the needed adc offset for voltage drop on the
// current measurement shunt
static int disp_i_to_u_adc_offset(int disp){
return(disp_u_to_adc(disp/20));
}
// convert adc values to voltage values, disp=10 is 1.0V
// disp_i_val is needed to calculate the offset for the voltage drop over
// the current measurement shunt
static int adc_u_to_disp(int adcunits,int disp_i_val){
int adcdrop;
adcdrop=disp_i_to_u_adc_offset(disp_i_val);
if (adcunits < adcdrop){
return(0);
}
adcunits=adcunits-adcdrop;
return((int)(((adcunits /102.3)* ADC_REF * U_DIVIDER)+0.6));
}
// convert adc values to current values, disp=10 needed to be printed
// by the printing function as 0.10 A
static int disp_i_to_adc(int disp){
return((int) (((disp * 10.23)* I_RESISTOR) / ADC_REF));
}
// convert adc values to current values, disp=10 needed to be printed
// by the printing function as 0.10 A
static int adc_i_to_disp(int adcunits){
return((int) (((adcunits* ADC_REF)/(10.23 * I_RESISTOR))+0.6));
}
// check the keyboard
static signed char check_buttons(void){
if (check_u_button(&(set_val[1]))){
if(set_val[1]>U_MAX){
set_val[1]=U_MAX;
}
return(1);
}
if (check_i_button(&(set_val[0]))){
if(set_val[0]>I_MAX){
set_val[0]=I_MAX;
}
return(1);
}
if (check_store_button()){
lcd_clrscr();
lcd_puts_P("store not");
lcd_gotoxy(0,1);
lcd_puts_P("implemented yet");
delay_ms(200);
return(1);
};
return(0);
}
void main(void)
{
char out_buf[20+1];
int measured_val[2];
measured_val[0]=0;
measured_val[1]=0;
init_dac();
lcd_init(LCD_DISP_ON);
init_kbd();
set_val[0]=15;set_val[1]=50; // 150mA and 5V
if (eeprom_read_byte((uint8_t *)0x0) == 19){
// ok magic number matches accept values
set_val[1]=eeprom_read_word((uint16_t *)0x04);
set_val[0]=eeprom_read_word((uint16_t *)0x02);
}
sei();
init_analog();
while (1) {
// current
measured_val[0]=adc_i_to_disp(getanalogresult(0));
set_val_adcUnits[0]=disp_i_to_adc(set_val[0]);
set_target_adc_val(0,set_val_adcUnits[0]);
// voltage
measured_val[1]=adc_u_to_disp(getanalogresult(1),measured_val[0]);
set_val_adcUnits[1]=disp_u_to_adc(set_val[1])+disp_i_to_u_adc_offset(measured_val[0]);
set_target_adc_val(1,set_val_adcUnits[1]);
// voltage
lcd_clrscr();
int_to_ascii(measured_val[1],out_buf,1,1);
lcd_puts(out_buf);
lcd_puts("V ");
int_to_ascii(set_val[1],out_buf,1,1);
lcd_putc('[');
lcd_puts(out_buf);
lcd_putc(']');
if (!is_current_limit()){
// put a marker to show which value is currenlty limiting
lcd_puts("<-");
}
// current
lcd_gotoxy(0,1);
int_to_ascii(measured_val[0],out_buf,2,0);
lcd_puts(out_buf);
lcd_puts("A ");
int_to_ascii(set_val[0],out_buf,2,0);
lcd_putc('[');
lcd_puts(out_buf);
lcd_putc(']');
if (is_current_limit()){
// put a marker to show which value is currenlty limiting
lcd_puts("<-");
}
//dbg
//int_to_ascii(is_dacval(),out_buf,0,0);
//lcd_puts(out_buf);
// the buttons must be responsive but they must not
// scroll too fast if pressed permanently
if (!check_buttons()){
// no buttons pressed
delay_ms(100);
check_buttons();
delay_ms(100);
}else{
delay_ms(200);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -