Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Adc pwm with hysteresis

Status
Not open for further replies.

fazenfact81

New Member
Hi to you all.

I am stuck with my pwm project. It is a simple pwm project with some button inputs and one ADC input. The problem I sit with is that when the button input initializes the ADC reading will immediately change the PWM as it is an actual reading and has to me executed because the condition is true!
So I try to build in some hysteresis in the ADC reading so that if there is some jitter on the ADC input it will be ignored until it exceeds the threshold. The way I have done it worked for a while like needed and I then expanded the code to do some other things and the ADC became reluctant to react. Then I reprogramed with the code that worked but no change, still very slow. I tried a lot of things and searched the net but did not come across a solution.
This for the background. Sorry for the long description but I try to explain so you could understand my project better and could provide me with better advice.
Attached is my code, please help me overcome the problem and help me learn out of it
Code:
 sbit UP at RB1_bit;
 sbit DOWN at RB0_bit;
 sbit OFF at RB2_bit;
 sbit Half at RB3_bit;
 sbit ON at RB4_bit;
 sbit STROBE at RB5_bit;
 unsigned short new_DC, current_DC, k;
 unsigned int ADR, old_ADR;


 void debounce(){
  Delay_ms(50);
 }

 void Button_ON(){
  PWM1_Set_Duty(current_DC);
  new_DC = 255;
  Delay_ms(20);
 }

 void Button_Half(){
  PWM1_Set_Duty(current_DC);
  new_DC = 75;
  Delay_ms(20);
 }

 void Button_OFF(){
  PWM1_Set_Duty(current_DC);
  new_DC = 0;
  Delay_ms(20);
 }

 void main() {

 ANSEL = 0x04;       // Configure analog pins
 ANSELH = 0;         // Configure digital pins
 TRISD = 0;          // Port D pins configured
 PORTD = 0x00;       // Port D initial state
 PORTC = 0x01;       // Port C initial state
 TRISC = 0;          // Port C pins configured
 PORTB = 0xFF;       // Port B initial state
 TRISB = 0xFF;       // PORT B set as output
 PORTA = 0xFF;       // Port A initial state
 TRISA = 0x02;       // RA input for pot
 ADCON1 = 0x82;      // A/D voltage reference is VCC
 ADC_Init();         // Initializes ADC
 C1ON_bit = 0;       // Disable comparators
 C2ON_bit = 0;       //
 old_ADR = 0;        // Initial value of variable ADR
 PWM1_Init(5000);    // PWM module initialization (5KHz)
 new_DC = 0;         // Initial value of variable Duty Cycle
 current_DC = 0;     // Initial value of variable Duty Cycle
 PWM1_Start();       // Start PWM1 module
 PWM1_Set_Duty(current_DC);


 k=0;
 while(k<3)
 {
    PORTC = 0x01;
    Delay_ms(80);
    PORTC = 0x00;
    Delay_ms(150);
    k++;
 }

 PORTC = 0x00;
 Delay_ms(200);
 PORTC = 0x01;      //Set PORTC


  do {
     if (!ON){               // If Button is pressed
      Button_ON();
      }
     if (!Half){             // If Button is pressed
      Button_Half();
      }
     if (!OFF){              // If Button is pressed
      Button_OFF();
      }
     if (!UP){               // If the button is pressed
      debounce();
      if (new_DC < 255)      // Don't go above 255
      new_DC = new_DC + 1 ;  // increment Duty Cycle by 1
           }
     if (!DOWN) {            // If the button is pressed
      debounce();
      if (new_DC !=0)        // Don't go below 0
      new_DC= new_DC - 1 ;   // Decrement Duty Cycle by 1
      }

      ADR = ADC_Read(1) >>2; //Get ADC reading and divide reading

      if (ADR < (old_ADR - 2)){
         new_DC = ADR;             // Set new_DC to ADR
       }

      if (ADR > (old_ADR + 2)){
         new_DC = ADR;            // Set new_DC to ADR
       }

      if (old_ADR != ADR){
         old_ADR = ADR;           // Set new_DC to ADR
       }

      if (current_DC != new_DC) {
      current_DC = new_DC ;
      PWM1_Set_Duty(current_DC); // Change the current DC to new value
      PORTD = current_DC;
      }

      if (!STROBE){
         PWM1_Set_Duty (0);
         k=0;
           while(k =! k)
              {
              PORTC.B1 = 1;
              PORTC.B2 = 1;
              Delay_ms(20);
              PORTC.B1 = 0;
              PORTC.B2 = 0;
              Delay_ms(45);
              k++;
              }


              PWM1_Start();
              PWM1_Set_Duty(current_DC);

        }

 } while(1);
}
 
if (old_ADR != ADR){
old_ADR = ADR; // Set new_DC to ADR
}


That line of code overrides all the other "If" conditionals.. I don't know what your goal is, but write the ADC code as a separate function. Maybe then the code becomes more readable.

Edit: Ok, missread your code.. I have no idea what you are trying to do.
 
I don't understand.. When you press a button, you set the "new_dc" variable to a certain value. But, in the main loop you read the ADC value and assign that to the same "new_dc" variable... Could you explain what are you trying to do. It seems like a simple application, but you are overthinking it.
 
Hi misterT,

Really appreciate you response.

Oke as this is my first project i expected a lot of bad coding. I need to drive a motor and need 2 tipes of inputs. A pot and buttons.
The Pot is the mail input if i can call it that way and the buttons is secondary inputs.
The main function of the buttons will be to set pwm 0,50,100%.
And the pot can then set pwm from 0-100%.

And yes i did overthink it but will learn how to become more efficient as i do more projects i hope. With your help i know ill do:)
 
Last edited:
When you press a button, you set the "new_dc" variable to a certain value. But, in the main loop you read the ADC value and assign that to the same "new_dc" variable...
Must i rather let the ADC use its own duty cycle to compare to?
 
First make the thing respond to the pot only.. forget the buttons.
When you get that working then start thinking about the buttons.

You did not mention how you want the buttons to work. If you press a "50%" button, should you keep it down or press it once? What happens when you release the button? How do you go from "button control" to "pot control"?

But, I repeat, Get the pot control working first and forget the buttons.
 
Oke ill do as you suggested,

The buttons then will need to be pressed once and set and set the pwm, and then when the pot input changes it must then set the pwm according to the pot and override the button input, and then if a new button input is given then it must override the pot and so on.

Really appreciate your effort in helping!
 
Ok I have changed the code so it only reads the pot. That works fine and looks like it doing what it should.
So when this worked fine i then added the button functions witch also works but if the pot is set and a button is pressed the pot then sets the pwm without me changing it. Can you help me overcome this problem pls. To be honest I have not a real idea how to do it
 
Why if when I add the -1 and +1 in this part of the code the adc reading have a huge "dead" spot? For more then 50% of the travel of the pot nothing happens?

Code:
if (ADR < (old_ADR-1)){
        new_DC = ADR;          
      }

      if (ADR > (old_ADR+1)){
        new_DC = ADR;        
      }

could some one help me!
 
Status
Not open for further replies.

Latest threads

Back
Top