re; any help mppt

hgmjr

Joined Jan 28, 2005
9,027
If you don't mind maybe you could post a fresh copy of your source code. It has been a while since this post was started and like the hardware the software has changed a bit at least since the start.

I still think you need to abandon the interrupt service routine in favor of a normal subroutine call. At the moment it is an added complication and doesn't bring anything to the party.

The last thing you need right now is to have to master the concept of interrupts. There will be time for that exercise later once things are up and running normally.

hgmjr
 

Thread Starter

olusola

Joined May 21, 2007
74
Rich (BB code):
Higher_Increase:;
    inc DAC_out_L;
    brcc Finish;
    inc DAC_out_H;
    rjmp Finish;

Actually I think all you will need to do is change the brcc instruction to brne and nothing else needs to be added.

The reason is that the inc instruction affects the Z-flag in the Status-Reg and brne tests the Z-flag when the byte goes from 255 to 0.

You have a copy of the ATMEL document that describes the AVR instruction set in detail, right? Take a look at the instructions we are discussing and you will see what I am talking about.

hgmjr


i still am not clear on this. the reason is that we have not compared anything so i am wondering how to use BRNE when we have not compared anything.

thanks
 

hgmjr

Joined Jan 28, 2005
9,027
i still am trying to understand the use of brne in this situation.
well is it a situation where the software wont put a carry and hence do you suggest we address this situation by ugoin
i still am not clear on this. the reason is that we have not compared anything so i am wondering how to use BRNE when we have not compared anything.

thanks
Take a look at the ATMEL instruction set document at the section on the INC instruction. You will see that when the result of the increment rolls over to 0 from 255, the Z-flag is set.

The BRNE instruction tests the Z-flag to determine whether to branch or not.

This is why I believe BRNE is the correct instruction to use here.

hgmjr

PS. I also tested it in AVRSTUDIO and it worked correctly.
 

Thread Starter

olusola

Joined May 21, 2007
74
Hi,
shown below is the updated code;
i tried not to disturb the previous algorithm while also trying to ensure i do not get any 0 decremented to 255 OR 255 incremented to 0;
please feel free to comment and test it .

thanks for your help. i'm still yet to test it on the hardware.


/*
--------------------------------------------------
Maximum Power Point Tracking
--------------------------------------------------
Olusola Osinowo
Ver 1.2 **NO Interrupts!
2007
--------------------------------------------------
ATmega16 Microcontroller
*/

//===========================================================================================
// Port and variable bit definitions:
;
; PortA:
; Bit 0 (ADC0): Voltage Input positive
; Bit 1 (ADC1): Current Input positive
;
; PortB:
; Bit0: Output to DAC LSB
; Bit1: Output to DAC
; Bit2: Output to DAC
; Bit3: Output to DAC
; Bit4: Output to DAC
; Bit5: Output to DAC
; Bit6: Output to DAC
; Bit7: Output to DAC
;
; PortD:
; Bit0: Output to DAC
; Bit1: Output to DAC MSB
;
;
; Move_Status:
; Bit0: Right (increasing Voltage) --> low; left (decreasing voltage) --> high

//===========================================================================================



// Inclued ATmega 16 definition
.include "m16def.inc"

// Variable definitions


// Outputs
// --> Power Output only

// Internal Calculation


.def Mul_H = r1; --> Multiplier MSB
.def Mul_L = r0; --> Multiplier LSB
.def Power_Old_H = r2;
.def Power_Old_M = r3
.def Power_Old_L = r4
.def Power_New_H = r5
.def Power_New_M = r6
.def Power_New_L = r7

.def Move_Status = r17
.def Voltage_H = r19
.def Voltage_L = r20
.def Current_H = r21
.def Current_L = r22
.def Temp = r23
.def DAC_out_H = r24
.def DAC_out_L = r25


//-----------------------------------------------------------------------------------------
// Interrupt definition
// Reset
.org $000 jmp Main;
// Interupt Timer 1
.org $00C jmp MPPT;
// -----------------------------------------------------------------------------------------

// Main function:
Main:

cli; //disabling interupts

// Clear Inputs

clr Voltage_H;
clr Voltage_L;
clr Current_H;
clr Current_L;
clr Power_New_H;
clr Power_New_M;
clr Power_New_L;
clr Power_Old_H;
clr Power_Old_M;
clr Power_Old_L;
clr Mul_H;
clr Mul_L;
clr Temp;
clr DAC_out_H;
clr DAC_out_L;
clr Move_Status;


// Initial Stack pointer
ldi Temp, LOW(RAMEND);
out SPL, Temp;
ldi Temp, HIGH(RAMEND);
out SPH, Temp;


// Initialise Timer 1
ldi Temp, 0b00010000;
out OCR1AH, Temp;
ldi Temp, 0b00000000;
out OCR1AL, Temp;
ldi Temp, 0b00001001;
out TCCR1B, Temp;
ldi Temp, 0b00010000;
out TIMSK, Temp;


// Initialise AD Converter
sbi ADCSRA, 7; set ADEN - enable AD converter
cbi ADCSRA, 2; set ADC clock prescaler
sbi ADCSRA, 1; set ADC clock prescaler
cbi ADCSRA, 0; set ADC clock prescaler

// Set input-output directions
ldi Temp, 0b00000000;
out DDRA, Temp; Port A Input
out PORTA, Temp;

ldi Temp, 0b11111111;
out DDRB, Temp; Port B Output

ldi Temp, 0b00000011;
out DDRD, Temp; Port D Output


//***** First Conversion - Discard)

ldi Temp, (1<<REFS1)|(1<<REFS0)|(0<<MUX0); set voltage meausurement channel and internal referece
out ADMUX, Temp;
sbi ADCSRA, ADSC; start A-D conversion

ADC_wait_K:; wait until A-D conversion finished
sbis ADCSRA, ADIF;
rjmp ADC_wait_K;

in Voltage_L, ADCL; Store Converted Low Bit value
in Voltage_H, ADCH; Store Converted High Bit value
//sbi ADCSRA, ADIF;

//******

//Inital Reference Values

//Measure Voltage
ldi Temp, (1<<REFS1)|(1<<REFS0)|(0<<MUX0); set voltage meausurement channel and internal referece
out ADMUX, Temp;
sbi ADCSRA, ADSC; start A-D conversion

ADC_wait_B:; wait until A-D conversion finished
sbis ADCSRA, ADIF;
rjmp ADC_wait_B;

in Voltage_L, ADCL; Store Converted Low Bit value
in Voltage_H, ADCH;


// Measure Current
ldi Temp, (1<<REFS1)|(1<<REFS0)|(1<<MUX0); set voltage meausurement channel and internal referece
out ADMUX, Temp;
sbi ADCSRA, ADSC; start A-D conversion

ADC_wait_C:; wait until A-D conversion finished
sbis ADCSRA, ADIF;
rjmp ADC_wait_C;

in Current_L, ADCL; Store Converted Low Bit value
in Current_H, ADCH; Store Converted High Bit value
//sbi ADCSRA, ADIF;

// Calculate Power Performing 10bit x 10bit = 24bit multiplication
// Power Calculated for first value to be used a start of climbing Algorithm

mul Voltage_H, Current_H; AH*BH
mov Power_Old_H, Mul_L;
mul Voltage_L, Current_L; AL*BL
mov Power_Old_M, Mul_H;
mov Power_Old_L, Mul_L;
mul Voltage_H, Current_L; AH*BL
add Power_Old_H, Mul_H;
add Power_Old_M, Mul_L;
mul Current_H, Voltage_L; BH*AL
add Power_Old_H, Mul_H;
add Power_Old_M, Mul_L;


//sei; // Enable Global Interrupts...

// Continuous loop

Loop_here:

idle_loop:; Top of idle loop
// Delay Loop
clr Temp; Clear Temp register

inner_loop:
dec Temp; Decrement Temp register
brne inner_loop; branch is Temp is not equal to 0

Call MPPT; Call the MPPT subroutine

rjmp idle_loop; Loop again


rjmp Loop_here



//=============================================================================
// Timer 1 interrupt routinte - MPPT
MPPT:

// Reset Timer 1 clock counter
clr Temp;
out TCNT1H, Temp;
out TCNT1L, Temp;


// Measure Voltage
ldi Temp, (1<<REFS1)|(1<<REFS0)|(0<<MUX0); set voltage meausurement channel and internal referece
out ADMUX, Temp;
sbi ADCSRA, ADSC; start A-D conversion

ADC_wait_V:; wait until A-D conversion finished
sbis ADCSRA, ADIF;
rjmp ADC_wait_V;

in Voltage_L, ADCL; Store Converted Low Bit value
in Voltage_H, ADCH; Store Converted High Bit value
//sbi ADCSRA, ADIF;

// Measure Current
ldi Temp, (1<<REFS1)|(1<<REFS0)|(1<<MUX0); set voltage meausurement channel and internal referece
out ADMUX, Temp;
sbi ADCSRA, ADSC; start A-D conversion

ADC_wait_E:; wait until A-D conversion finished
sbis ADCSRA, ADIF;
rjmp ADC_wait_E;

in Current_L, ADCL; Store Converted Low Bit value
in Current_H, ADCH; Store Converted High Bit value
//sbi ADCSRA, ADIF;

// Calculate Power Performing 10bit x 10bit = 24bit multiplication
mul Voltage_H, Current_H; AH*BH
mov Power_New_H, Mul_L;
mul Voltage_L, Current_L; AL*BL
mov Power_New_M, Mul_H;
mov Power_New_L, Mul_L;
mul Voltage_H, Current_L; AH*BL
add Power_New_H, Mul_H;
add Power_New_M, Mul_L;
mul Current_H, Voltage_L; BH*AL
add Power_New_H, Mul_H;
add Power_New_M, Mul_L;


// Control Output - Perturb Algorithm

cp Power_New_H, Power_Old_H;
breq Equal_H;
brlo Lower;
rjmp Higher;

Equal_H:
cp Power_New_M, Power_Old_M;
breq Equal_M;
brlo Lower;
rjmp Higher;

Equal_M:
cp Power_New_L, Power_Old_L;
breq Equal_L;
brlo Lower;
rjmp Higher;

Lower:; move Voltage in oposite direction
sbrc Move_Status, 0;
rjmp Lower_Increase;
rjmp Lower_Decrease;

Lower_Decrease:;
sbr Move_Status, 0;
cpi DAC_out_L,0; if equal to 0 break - do not decrease further
breq Finish; this leaves it at 0
dec DAC_out_L;
cpi DAC_out_L, 255;
brne Finish;
cpi DAC_out_H,0; if equal to 0 break - do not decrease further
breq Finish; this leaves it at 0
dec DAC_out_H;
rjmp Finish;

Lower_Increase:;
cbr Move_Status, 0;
cpi DAC_out_L,255; if equal to 255 - break- do not decrease futher
breq Finish; leave it at 3FFh
inc DAC_out_L;
brcc Finish;
cbr Move_Status, 0;
cpi DAC_out_H,255; if equal to 255 - break- do not decrease futher
breq Finish; leave it at 3FFh
inc DAC_out_H;
rjmp Finish;

Higher:; move Voltage same direction as before
sbrc Move_Status, 0
rjmp Higher_Decrease;
rjmp Higher_Increase;

Higher_Decrease:;
cpi DAC_out_L,0; if equal to 0 break - do not decrease further
breq Finish; this leaves it at 0
dec DAC_out_L;
cpi DAC_out_L, 255;
brne Finish;
cpi DAC_out_H,0; if equal to 0 break - do not decrease further
breq Finish; this leaves it at 0
dec DAC_out_H;
rjmp Finish;

Higher_Increase:;
cpi DAC_out_L,255; if equal to 255 - break- do not decrease futher
breq Finish; leave it at 3FFh
inc DAC_out_L;
brne Finish;
cpi DAC_out_H,255; if equal to 0 break - do not decrease further
breq Finish; this leaves it at 0
inc DAC_out_H;
rjmp Finish;

Equal_L:; equal value --> do nothing


Finish:; set outputs

out PORTB, DAC_out_L;
out PORTD, DAC_out_H;


// Set New power to old power
mov Power_Old_H, Power_New_H;
mov Power_Old_M, Power_New_M;
mov Power_Old_L, Power_New_L;

// return from interrupt
ret;
 

Thread Starter

olusola

Joined May 21, 2007
74
Another thing i think i did forget to mention is a suggestion, that the previous system might have been hanging around the high current part in the IV curve. i have attached a quickly drawn graph to show the region i suspect.

well i thought i'd mention this just incase there might be any bug that you think might be responsible for this.

I am also hoping that its not that the range of change of the ADC does not reach the lower voltage values of the MOSFET where it will offer more resistance? - hence move lower on the curve? V= IR hence V is proportional to R?

thanks
 

Attachments

hgmjr

Joined Jan 28, 2005
9,027
I have loaded it into the AVRSTUDIO and it compile without any errors.

I'll take a look at the code and get back with comments.

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,027
Another thing i think i did forget to mention is a suggestion, that the previous system might have been hanging around the high current part in the IV curve. i have attached a quickly drawn graph to show the region i suspect.

well i thought i'd mention this just incase there might be any bug that you think might be responsible for this.

I am also hoping that its not that the range of change of the ADC does not reach the lower voltage values of the MOSFET where it will offer more resistance? - hence move lower on the curve? V= IR hence V is proportional to R?

thanks
The DAC's output available at the output of the second opamp (powered by +/-10V) should be able to go pretty close to ground. The mosfet would have gone to an open circuit condition for all practical purpose once its gate voltage fell below +2 volts if not sooner.

hgmjr
 

Thread Starter

olusola

Joined May 21, 2007
74
Rich (BB code):
Loop_here:

idle_loop:; Top of idle loop
// Delay Loop
clr Temp; Clear Temp register

inner_loop:
dec Temp; Decrement Temp register
brne inner_loop; branch is Temp is not equal to 0

Call MPPT; Call the MPPT subroutine

rjmp idle_loop; Loop again


rjmp Loop_here

please do you confirm that this loop is ok?

thanks
 

hgmjr

Joined Jan 28, 2005
9,027
Rich (BB code):
Loop_here:
idle_loop:; Top of idle loop
// Delay Loop clr Temp; Clear Temp register inner_loop: dec Temp; Decrement Temp register brne inner_loop; branch is Temp is not equal to 0​
Call MPPT; Call the MPPT subroutine​
rjmp idle_loop; Loop again​
rjmp Loop_here


please do you confirm that this loop is ok?

thanks
The two statements highlighed in red are not necessary.

Your idle_loop is where much of the processing time will be spent.

The inner loop label inner_loop is there to provide a short delay.

Once the system is up and running, more delay or less delay may be called for to optimize the overall perfromance.

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,027
Attached is the updated code.

thanks for your help.
please feel free to comment on any part of the code .

cheers

olu
I have imported the code over and it compiled first time.

You are getting the hang of this assembly code.

Good work.

hgmjr
 

hgmjr

Joined Jan 28, 2005
9,027
I really hope I am,
Maybe later, getting some tasks and trying to do them might help.

thanks for being there
The more Assembly Language programming you do, the easier it becomes.

You will know you have arrived when you have memorized the instruction set.

hgmjr
 

Thread Starter

olusola

Joined May 21, 2007
74
oh, yes,
can i say a big thank you to you for your help!
yes the demo was good. and it literally just worked
i am attaching some files to show this.
oh thanks so so much appreciate this.

cheers

olu
 

Attachments

Thread Starter

olusola

Joined May 21, 2007
74
oh, welll the story on it working:
well it at first, did not draw as much power, but then i decided to fiddle around and vary the DAC Vcc, (= DAC reference voltage = Op-amp voltage ).
while monitoring in real time, i gradually reduced it from 10V , it suddenly peaked power say about 7.8V and then came back down. it remained down, even till around 4V then i took it back up again, and from say like 7V, it then behaved well. drawing abuot 9W power from a 10W module, goood..

oh thanks again.


but do you seem to know why?
it looks like it like the voltage been taken gradually from 0 to 10V before it gets the hang of things.
 

hgmjr

Joined Jan 28, 2005
9,027
Happy to hear that the demo of your MPPT controller design was a success.

As for the graphs that you have provided, if you have a chance it would be helpful to know a bit more details on where in the circuit the plotter was attached so that we can get a better feel for how well it performed.

Good Luck
hgmjr
 

Thread Starter

olusola

Joined May 21, 2007
74
hi,
yes i used a PICO ADC11 which has 11analog inputs and max voltage of 2.5V.
this was nice as the design for the microcontroller is also 2.5V.
so i took the inputs at the same place i took the ones for the microcontroller.
these of course were not the actual voltages so i recalculated them from their proportions.
it is similar to the previous demo results calculations.


Olu
 
Top