Updating ADC to PWM

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i am working on a project whereby i want to use the value of my ADC to alter my PWM. i have been able to get my ADC value but i can only display it on LCD,it is not updating in the main menu. i  alsosimulated iti am getting excessive load error


//
volatile uint16_t Input_ADC_Voltage;
volatile uint16_t Input_ADC_Current;

int main(void)
{
	
	DDRB |= (1<<DDB1) | (1<<DDB2);
	
	LCDSetup(LCD_CURSOR_NONE);
	
	
	ICR1 = 160;
	OCR1A = Input_ADC_Current;
	
		
	TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
	TCCR1A |= 1<<WGM11;
	TCCR1B |= (1<<WGM12) |(1<<WGM13);
	
	TCCR1B |=1<<CS10;
	

	
	
	ADCSRA |= (1<<ADPS2) |(1<<ADPS1);
	ADMUX |= (1<<REFS0);
	ADCSRA |= 1<<ADIE;
	ADCSRA|= 1<<ADEN;
	
	sei();
	
	ADCSRA |= 1<<ADSC;
	
	
	
	
	while (1)
	{
	
		LCDWriteIntXY(1, 1, Input_ADC_Current, 4);
	}
}

ISR(ADC_vect)
{
	uint8_t Low_bit = ADCL;
	uint16_t Max_Bit_Result = ADCH<<8 | Low_bit;

	switch (ADMUX)
	{
		//Input Voltage
		case 0x40:
		Input_ADC_Current = Max_Bit_Result;
		//LCDWriteIntXY(1, 1, Input_ADC_Current, 4);
		ADMUX = 0x41;
		break;
		
		//Input Current
		case 0x41:
		Input_ADC_Voltage = Max_Bit_Result;
		//LCDWriteIntXY(1, 2, Input_ADC_Voltage, 4);
		ADMUX = 0x42;
		break;
		
		//OUtput Voltage
		case 0x42:
		Output_ADC_Voltage = Max_Bit_Result;
		//LCDWriteIntXY(1, 3, Output_ADC_Voltage, 4);
		ADMUX = 0x43;
		break;
		
		//Output Current
		case 0x43:
		Output_ADC_Current = Max_Bit_Result;
		//LCDWriteIntXY(1, 4, Output_ADC_Current, 4);
		ADMUX = 0x40;
		break;
		
		
		default:
		//Default code
		break;
	} 
	ADCSRA |= 1<<ADSC;
}

The first value is the actual value of my ADC while the second one showing "0000" is suppossed to be my PWM value. i use 100KHz frequency with the view of altering the duty circle. 

Attachment(s): 

This topic has a solution.
Last Edited: Mon. Sep 9, 2019 - 05:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please post the source that can be built normally.
Otherwise it is not worth investigating.

 

Since you are not operating OCR1A other than initialization, the PWM never changes.
There is only one LCDWriteIntXY in the while loop. It is a mystery what "0000" represents.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include "display.h"


volatile uint16_t Input_ADC_Voltage;
volatile uint16_t Input_ADC_Current;
volatile uint16_t Output_ADC_Voltage;
volatile uint16_t Output_ADC_Current;



int main(void)
{
	float V;	
	DDRB |= (1<<DDB1) | (1<<DDB2);
	
	LCDSetup(LCD_CURSOR_NONE);
	
	V = Input_ADC_Current/6.4;
	
	ICR1 = 160;
	OCR1A = V;
	//OCR1B = Input_ADC_Voltage;
		
	TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
	TCCR1A |= 1<<WGM11;
	TCCR1B |= (1<<WGM12) |(1<<WGM13);
	
	TCCR1B |=1<<CS10;
	
	
	
	
	ADCSRA |= (1<<ADPS2) |(1<<ADPS1);
	ADMUX |= (1<<REFS0);
	ADCSRA |= 1<<ADIE;
	ADCSRA|= 1<<ADEN;
	
	sei();
	
	ADCSRA |= 1<<ADSC;
	
	
	
	
	while (1)
	{
	
		LCDWriteIntXY(1, 1, Input_ADC_Current, 4);
		LCDWriteIntXY(8,1,V,4);
	}
}

ISR(ADC_vect)
{
	uint8_t Low_bit = ADCL;
	uint16_t Max_Bit_Result = ADCH<<8 | Low_bit;

	switch (ADMUX)
	{
		//Input Voltage
		case 0x40:
		Input_ADC_Current = Max_Bit_Result;
		//LCDWriteIntXY(1, 1, Input_ADC_Current, 4);
		ADMUX = 0x41;
		break;
		
		//Input Current
		case 0x41:
		Input_ADC_Voltage = Max_Bit_Result;
		//LCDWriteIntXY(1, 2, Input_ADC_Voltage, 4);
		ADMUX = 0x42;
		break;
		
		//OUtput Voltage
		case 0x42:
		Output_ADC_Voltage = Max_Bit_Result;
		//LCDWriteIntXY(1, 3, Output_ADC_Voltage, 4);
		ADMUX = 0x43;
		break;
		
		//Output Current
		case 0x43:
		Output_ADC_Current = Max_Bit_Result;
		//LCDWriteIntXY(1, 4, Output_ADC_Current, 4);
		ADMUX = 0x40;
		break;
		
		
		default:
		//Default code
		break;
	} 
	ADCSRA |= 1<<ADSC;
}

that is the complete code i simulated (if by these you mean source, otherwise i don't understand what you mean)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are showing V but have never changed. Therefore, OCR1A is never changed.

 

I don't know what you want, but isn't this kind of code probably missing in the while loop?

    cli();
    OCR1A = Input_ADC_Current/6.4f;
    sei();

 

And I don't know what LCDWriteIntXY is, but I expect the third argument to be int16_t. Is it okay to put V as a float?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My main issue is V not displaying the value of input current as written.the ADC values only display if I call it in the ISR. Otherwise, it will output 0000. That is why V is not updating.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Putting that switch in the ISR is not a good practice.  Better to get your ADC result and save it to a Volatile variable and get out of the ISR and let the switch reside in MAIN.

 

Why do you need a FLOAT for V?  Some integer math should do the trick.  Might want to use simple integers until you get things working THEN start making your life difficult.

 

This:

uint16_t Max_Bit_Result = ADCH<<8 | Low_bit;

Does not look right. 

 

THis:

while (1)
	{
	
		LCDWriteIntXY(1, 1, Input_ADC_Current, 4);
		LCDWriteIntXY(8,1,V,4);
	}

I don't know of any LCD's that have 8rows so the second line is kinda odd.

 

 

It looks like you are trying to read four voltages(currents, whatever) and display them on an LCD.  Suggestions

 

Set up an ADC function where you read these four inputs and store them in a structure.

Create a math function that will convert the reading to the values you desire, and store them back into a structure

Then create a function to update your LCD with your readings.

 

THis will make your life...and ours easier to decipher what you are doing, and makes troubleshooting easier as issues can be narrowed down to specific parts as opposed to one big mish mash.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where is V updated in your program?
There is no code to update V in the while loop. Of course also in interrupt processing.

Naturally it will keep “0” forever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Following the above comments, i was able to edit and got the values i wanted (or so i thought). i am using the microcontroller such that i can adjust the variable at the ADC tothe PWM using 100KHz

Is there anything i am missing or that i can add to tidy it up

/*
 * Bench_Power.c
 *
 * Created: 18/08/2019 11:35:55 AM
 * Author : H2dt Services
 */ 

#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include "display.h"


uint16_t Input_ADC_Current;
uint16_t Input_ADC_Voltage;
uint16_t Output_ADC_Current;
uint16_t Output_ADC_Voltage;



volatile uint16_t Max_Bit_Result;

void Multiple_ADC()
{
	switch (ADMUX)
	{
		//Input Current
		case 0x40:
		Input_ADC_Current = Max_Bit_Result;
		LCDWriteIntXY(1, 1, Input_ADC_Current, 4);
		ADMUX = 0x41;
		break;
		
		//Input Voltage
		case 0x41:
		Input_ADC_Voltage = Max_Bit_Result;
		//LCDWriteIntXY(1, 2, Input_ADC_Voltage, 4);
		ADMUX = 0x42;
		break;
		
		//OUtput Current
		case 0x42:
		Output_ADC_Voltage = Max_Bit_Result;
		//LCDWriteIntXY(1, 3, Output_ADC_Voltage, 4);
		ADMUX = 0x43;
		break;
		
		//Output Voltage
		case 0x43:
		Output_ADC_Current = Max_Bit_Result;
		//LCDWriteIntXY(1, 4, Output_ADC_Current, 4);
		ADMUX = 0x40;
		break;
		
		
		default:
		//Default code
		break;
	}
	
}


void PWM_Convert()
{
	TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
	TCCR1A |= 1<<WGM11;
	TCCR1B |= (1<<WGM12) |(1<<WGM13);
	
	TCCR1B |=1<<CS10;
	ICR1 = 160;
}

int main(void)
{
		
	DDRB |= (1<<DDB1) | (1<<DDB2);
	
	LCDSetup(LCD_CURSOR_NONE);
	
		
	PWM_Convert();
	
		
	ADCSRA |= (1<<ADPS2) |(1<<ADPS1);
	ADMUX |= (1<<REFS0);
	ADCSRA |= 1<<ADIE;
	ADCSRA|= 1<<ADEN;
	
	sei();
	
	ADCSRA |= 1<<ADSC;
	
	
	
	
	while (1)
	{
	
		Multiple_ADC();
		
		OCR1A = (Input_ADC_Current/6.39);
		OCR1B = (Input_ADC_Voltage/6.39);
		
		LCDWriteIntXY(10,1, OCR1A,3);
		LCDWriteIntXY(10,2, OCR1B,3);
	}
}



ISR(ADC_vect)
{
	uint8_t Low_bit = ADCL;
	Max_Bit_Result = ADCH<<8 | Low_bit;

	ADCSRA |= 1<<ADSC;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

holawaleh wrote:
i was able to edit and got the values i wanted (or so i thought).

 

What does that mean?  Did you get the results or not?  I am guessing not.

 

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got the results, but I'll like to know why you think otherwise

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

holawaleh wrote:
but I'll like to know why you think otherwise

 

Simple.  The reason I think/thought otherwise is because you wrote this:

holawaleh wrote:
got the values i wanted (or so i thought)

 

 

Thats generally what people write when they get something, but not what they were expecting.

 

Hey, if it all works please mark the post that provided the solution, or has the solution so we know the thread is closed.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
	uint8_t Low_bit = ADCL;
	Max_Bit_Result = ADCH<<8 | Low_bit;

would be much simpler as:

	Max_Bit_Result = ADC;

(there's no need to read ADCL and ADCH separately).