Here is the complete code (in MIKROE BASIC for AVR, use similar code for other programming languages)
Also amended the previous post because the voltage is also read from the I2C (assumed is that the other PSU has exactly the same voltage)
[code start]
program ZeroChargerReadout
' * Description:
' This code shows the voltage, current and temperature on n FPS1000-48 PSU
' initialized, then some text is written, then the text is moved.
' * Test configuration:
' MCU: ATTiny28L
'
http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf' Dev.Board: EasyAVR6 - ac:LCD
'
http://www.mikroe.com/eng/products/view/321/easyavr6-development-system/' Oscillator: External Clock 08.0000 MHz
'module ZeroChargerReadout v2
'
http://www.mikroe.com/eng/products/view/277/various-components/' SW: mikroBasic PRO for AVR
'
http://www.mikroe.com/eng/products/view/226/mikrobasic-pro-for-avr/' * NOTES:
' - Turn on the LCD backlight on the EasyAVR6 board (SW10.7).
' *
' Declarations section
' LCD module connections
dim LCD_RS as sbit at PORTD2_bit
dim LCD_EN as sbit at PORTD3_bit
dim LCD_D4 as sbit at PORTD4_bit
dim LCD_D5 as sbit at PORTD5_bit
dim LCD_D6 as sbit at PORTD6_bit
dim LCD_D7 as sbit at PORTD7_bit
dim LCD_RS_Direction as sbit at DDD2_bit
dim LCD_EN_Direction as sbit at DDD3_bit
dim LCD_D4_Direction as sbit at DDD4_bit
dim LCD_D5_Direction as sbit at DDD5_bit
dim LCD_D6_Direction as sbit at DDD6_bit
dim LCD_D7_Direction as sbit at DDD7_bit
' End LCD module connections
' Software I2C connections
dim Soft_I2C_Scl_Output as sbit at PORTD0_bit
dim Soft_I2C_Sda_Output as sbit at PORTD1_bit
dim Soft_I2C_Scl_Input as sbit at PIND0_bit
dim Soft_I2C_Sda_Input as sbit at PIND1_bit
dim Soft_I2C_Scl_Direction as sbit at DDD0_bit
dim Soft_I2C_Sda_Direction as sbit at DDD1_bit
' End Software I2C connections
dim txt1,txt2 as char[16]
dim strvoltage as string[17]
dim strcurrent as string[17]
dim strtemperature as string[17]
dim strenergycalc as string[17]
dim strpower as string[17]
dim voltage as byte
dim current as byte
dim temperature as byte
dim channel4 as byte
dim voltagecalc as float
dim currentcalc as float
dim temperaturecalc as float
dim powercalc as float
dim energycalc as float
dim statusbyte as byte
dim displayrotation as byte
Main:
initialize:
Lcd_Init() ' Initialize LCD
Lcd_Cmd(_LCD_CLEAR) ' Clear display
Lcd_Cmd(_LCD_CURSOR_OFF) ' Cursor off
LCD_Out(1,1,"Zero SR Charger") ' Write text in first row
LCD_Out(2,1,"V2 Made by RH") ' Write text in second row
Delay_ms(2000) ' Display splash screen for 1 second
LCD_cmd(_LCD_Clear) ' Clear Display
Soft_i2c_init() ' Initialize I2C bus
Soft_i2c_Start() ' Issue start signal
Soft_i2c_Write(0x9E) ' Address PCF8591, see PCF8591 datasheet
Soft_I2c_Write(0x44) ' Set analog output and auto increment channel
Soft_I2c_Stop() ' Close I2C bus
displayrotation = 1 ' Set display rotation byte
energycalc = 0
loop:
while TRUE
read_I2C_analog:
Soft_I2C_Start() ' Issue start signal
Soft_I2C_Write(0x9F) ' Address PCF8591, see PCF8591 datasheet
channel4 = Soft_I2c_Read(1) ' first channel4 because it's always the result from the previous input (by design)
voltage = Soft_I2C_Read(1) ' Read voltage byte
current = Soft_I2C_Read(1) ' Read current byte
temperature = Soft_I2C_Read(0) ' Read Temperature byte and send not ack to indicate last byte read
Soft_I2C_Stop() ' Issue stop signal
read_I2C_digital:
Soft_I2C_Start() ' Issue start signal
Soft_I2C_Write(0x4F) ' Address PCF8574, see PCF8574 datasheet
statusbyte = Soft_I2C_Read(0) ' first channel4 because it's always the result from the previous input (by design)
Soft_I2C_Stop() ' Issue stop signal
Calculations:
voltagecalc = voltage*2.0*60.0/255.0 '8 bit resolution up to 60 Volts
floattostr(voltagecalc,strvoltage) 'convert to a string
strvoltage[5]=0 'truncate the first 5 characters of the string
currentcalc = current*25.0/255.0 ' 8 bit resolution up to 25 Amps
floattostr(currentcalc,strcurrent) ' convert to a string
strcurrent[4]=0 ' truncate to first 4 characters of the string
temperaturecalc = temperature*100.0/255.0 ' 8 bit resolution up to 100 degrees celcius
floattostr(temperaturecalc,strtemperature) ' convert to a string
strtemperature[4]=0 ' truncate to the first 4 characters
powercalc = voltagecalc*currentcalc/1000 ' calculate power from voltage * current and divide by 1000 to get kW
floattostr(powercalc,strpower) ' convert to a string
strpower[4]=0 ' truncate the first 4 characters of the string
energycalc = energycalc + powercalc/3600
floattostr(energycalc,strenergycalc)
strenergycalc[5]=0
statusbyte =statusbyte or 96
displayoutput:
txt1 = "V=" + strvoltage + "V I=" + strcurrent + "A" ' first line of the LCD : always displays the Voltage and Current
txt1[16]=0 ' truncate to 16 characters if neccessary to avoid weird screens
LCD_Out(1,1,txt1) ' Write text in first row
statusbyte = statusbyte and displayrotation ' check 1 alarm each loop (displayrotation shifts one bit to the left each loop)
Select case statusbyte
case 1 ' output fail
txt2="Output Fail "
Case 2 ' overtemp protect
txt2="Overtemp Protect"
Case 4 ' Temperature alarm
txt2="Temp alarm "
Case 8 ' Fan Fail
txt2="Fan Fail "
Case 16 ' Input Fail
txt2="Input Fail "
Case 32
txt2="E=" + strenergycalc + "kWh "
Case 64
txt2="E=" + strenergycalc + "kWh "
Case else
txt2 = "P=" + strpower + "kW T=" + strtemperature + "C" ' this line is displayed if
End select
txt2[16]=0 'truncate to 16 characters if neccessary to avoid weird screens
LCD_Out(2,1,txt2) ' Write text in second row
displayrotation = displayrotation *2 ' Shift displayrotation one bit to left
if displayrotation = 128 then displayrotation = 1 ' the second line shifts through 6 possible displays, 1 for each of 5 alarms and 1 for the power and temperature
end if
delay_ms(980) 'rest of the cycle is about 20ms, this generates a more excact 1 sec timebase without using interrupts
wend
end.