Electronics > Projects, Designs, and Technical Stuff

thoughts on my project

<< < (4/12) > >>

ali6x944:

--- Quote from: Prehistoricman on March 12, 2020, 12:02:11 pm ---Functions always specify a result type before the function name. If it's any type except for void, that means the function returns a value. Functions that do return must have a return statement. Functions that don't return must not have a return statement.

In the way you've set up your ADC_RESULT function, you shouldn't return. You're using a global variable RESULT to store the ADC_RESULT rather than a return value and return statement.
You've also incorrectly set up ADC_RESULT to accept an argument called RESULT. You can remove that. That's why your calls to ADC_RESULT are causing errors.

--- End quote ---
ok cool, so the function ADC_RESULT will become:

--- Code: ---uint16_t ADC_RESULT()
    {
        ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITS
        while(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ON
        RESULT = ADRESH << 8; //Load ADC high value
        RESULT |= ADRESL; //Load ADC low value
    }
main()
{
.
.
.
}
--- End code ---

--- Quote from: Prehistoricman on March 12, 2020, 12:02:11 pm ---Again, you don't want to ever leave main(). Your while loop will end if BIG_SW and SMALL_SW are not 1. The function will attempt to return to god knows where and if you're lucky, the microcontroller will reset.
And again, you're not updating BIG_SW or SMALL_SW. You only read from the GPIO port once.

--- End quote ---
for the updating of BIG_SW and SMALL_SW value, how can I do it without interrupting the PWM and ADC read cycle?
I was planing the for the addition of a sleep condition in the loop were if neither BIG_SW and SMALL_SW==1 then the micro goes to sleep.
 
--- Quote from: Prehistoricman on March 12, 2020, 12:02:11 pm ---So, my suggested changes are:
Remove the condition from the while loop and change it to while (true) or while (1). This is known as an infinite loop.
Inside the loop, read the button values into BIG_SW and SMALL_SW.
Think about all the register operations you have in the loop there. Do you need to run these all the time?

--- End quote ---
for the run time I would say the ADC AND TMR2 CCP1 are the only things that should run all the time.
I am trying to figure out if the sleep condition gonna screw up with something...

Prehistoricman:

--- Quote from: ali6x944 on March 12, 2020, 08:55:12 pm ---ok cool, so the function ADC_RESULT will become:

--- Code: ---uint16_t ADC_RESULT()
    {
        ADCON0bits.GOnDONE=1; // ADC CONVERSION STATUS BITS
        while(ADCON0bits.GOnDONE==1); // WAIT WHILE ADC STATUS IS ON
        RESULT = ADRESH << 8; //Load ADC high value
        RESULT |= ADRESL; //Load ADC low value
    }
main()
{
.
.
.
}
--- End code ---


--- End quote ---
Almost. Change the return type from uint16_t to void. This means the function does not return a value.


--- Quote from: ali6x944 on March 12, 2020, 08:55:12 pm ---for the updating of BIG_SW and SMALL_SW value, how can I do it without interrupting the PWM and ADC read cycle?
I was planing the for the addition of a sleep condition in the loop were if neither BIG_SW and SMALL_SW==1 then the micro goes to sleep.

--- End quote ---
Reading two bits from IO is hardly interrupting. What do you think the problem might be? The PWM module should continue doing its thing regardless of how long ADC readout or IO polling might take.

If you want to move to dealing with sleep, there's a couple of things to consider:
Pressing the buttons should wake the microcontroller (right?), so they need to be interrupt-driven, and the IO needs to be set up to deliver interrupts.
Does the PWM module operate in sleep mode? Some chips have multiple levels of sleep.

ali6x944:

--- Quote from: Prehistoricman on March 12, 2020, 10:16:31 pm ---If you want to move to dealing with sleep, there's a couple of things to consider:
Pressing the buttons should wake the microcontroller (right?), so they need to be interrupt-driven, and the IO needs to be set up to deliver interrupts.
Does the PWM module operate in sleep mode? Some chips have multiple levels of sleep.

--- End quote ---
well, hopefully, it will wake up if the state of the SMALL/BIG_SW changes or if the value of RESULT variable changes? not sure if this is possible??
after a bit of reading thou I think going for a combination of doze mode during operation and idle mode in the off condition is a good idea:

--- Quote ---11.1 DOZE Mode
DOZE mode allows for power saving by reducing CPU
operation and program memory (PFM) access, without
affecting peripheral operation. DOZE mode differs from
Sleep mode because the system oscillators continue to
operate, while only the CPU and PFM are affected. The
reduced execution saves power by eliminating
unnecessary operations within the CPU and memory.
When the Doze Enable (DOZEN) bit is set (DOZEN =
1), the CPU executes only one instruction cycle out of
every N cycles as defined by the DOZE<2:0> bits of the
CPUDOZE register. For example, if DOZE<2:0> = 100,
the instruction cycle ratio is 1:32. The CPU and
memory execute for one instruction cycle and then lay
idle for 31 instruction cycles. During the unused cycles,
the peripherals continue to operate at the system clock
speed
11.3 IDLE Mode
When the Idle Enable (IDLEN) bit is clear (IDLEN = 0),
the SLEEP instruction will put the device into full Sleep
mode (see Section 11.2 “Sleep Mode”). When IDLEN
is set (IDLEN = 1), the SLEEP instruction will put the
device into IDLE mode. In IDLE mode, the CPU and
memory operations are halted, but the peripheral
clocks continue to run. This mode is similar to DOZE
mode, except that in IDLE both the CPU and PFM are
shut off.

--- End quote ---
for one I will get a lower power consumption during operation and power-down, and relatively easy wake-up code -I think-.
the questions become how can I implement them in the loop?
I was thinking of something like this:

--- Code: ---.
.
.
int main()
{
.
.
.
[the doze mode setup]
while(BIG_SW==1||SMALL_SW==1)
{
.
.
.
}
if (BIG_SW!=1&&SMALL_SW!=1)
{
[sleep mode setup]
}
}


--- End code ---

Prehistoricman:

--- Quote from: ali6x944 on March 14, 2020, 08:19:31 am ---well, hopefully, it will wake up if the state of the SMALL/BIG_SW changes or if the value of RESULT variable changes? not sure if this is possible??

--- End quote ---
Not really. Sleep generally halts or resets the CPU. You have no variables, code execution, whatever. You won't be able to initiate ADC reads at all.
This doze mode is interesting though. It basically slows down the CPU. Probably doesn't save a lot of power compared to idle/sleep.


--- Quote from: ali6x944 on March 14, 2020, 08:19:31 am ---for one I will get a lower power consumption during operation and power-down, and relatively easy wake-up code -I think-.
the questions become how can I implement them in the loop?
I was thinking of something like this:

--- Code: ---.
.
.
int main()
{
.
.
.
[the doze mode setup]
while(BIG_SW==1||SMALL_SW==1)
{
.
.
.
}
if (BIG_SW!=1&&SMALL_SW!=1)
{
[sleep mode setup]
}
}


--- End code ---

--- End quote ---
That could work. You can move the sleep stuff to be after the loop. You drop out of the loop when neither button is pressed, then go to sleep.
Make sure you have the interrupts for wake-up set up on your two button GPIOs.
You should always (again) make sure that main() ends with an infinite loop. So after initialising sleep, loop forever.

ali6x944:

--- Quote from: Prehistoricman on March 14, 2020, 12:41:52 pm ---That could work. You can move the sleep stuff to be after the loop. You drop out of the loop when neither button is pressed, then go to sleep.
Make sure you have the interrupts for wake-up set up on your two button GPIOs.
You should always (again) make sure that main() ends with an infinite loop. So after initialising sleep, loop forever.

--- End quote ---
well, can I implement that by a simple While(1) loop which the while(BIG_SW==1||SMALL_SW==1) and an if statement where the sleep instruction is placed?
and for the interrupts, I really don't know how to set up those :-[ ; but here I go so bear with me:

--- Quote ---10.3 Interrupts During Sleep
Interrupts can be used to wake from Sleep. To wake
from Sleep, the peripheral must be able to operate
without the system clock. The interrupt source must
have the appropriate Interrupt Enable bit(s) set prior to
entering Sleep.
On waking from Sleep, if the GIE bit is also set, the
processor will branch to the interrupt vector. Otherwise,
the processor will continue executing instructions after
the SLEEP instruction. The instruction directly after the
SLEEP instruction will always be executed before
branching to the ISR. Refer to Section 11.0 “Power-
Saving Operation Modes” for more details.

--- End quote ---
so according to this, the peripheral used to wake up the CPU must be able to operate without the system clock, and here we will be using BIG/SMALL_SW as our interrupt source, the question is how many external interrupt pins do I have? here I found two different things in the datasheet, a External interrupt input and Interrupt-on-change input both can wake up the cpu from sleep...
so I looked up this IOC thingy and came up with this:

--- Quote ---17.0 INTERRUPT-ON-CHANGE
An interrupt can be generated by detecting a signal that
has either a rising edge or a falling edge. Any individual
pin, or combination of pins, can be configured to
generate an interrupt. The interrupt-on-change module
has the following features:
• Interrupt-on-Change enable (Master Switch)
• Individual pin configuration
• Rising and falling edge detection
• Individual pin interrupt flags
Figure 17-1 is a block diagram of the IOC module.

--- End quote ---
so this looks more promising, so I have to set the ioc and IOCIE bit of the PIE0 registers for both RA4 and  RA5 which is my BIG/SMALL_SW pins to falling edge trigger...
So this is what I came with, notice I did not include the idle setup yet:

--- Code: ---int main(void)
{
    OSCFRQ=0b010; // OSCFRQ(HFFRQ0-2) SET OSCILLATOR TO 4MHz
   
    TRISAbits.TRISA0=0; // TRISA0(RA0) BIG LIGHT DRIVE, OUTPUT
    TRISAbits.TRISA1=0; // TRISA1(RA1) SMALL LIGHT DRIVE, OUTPUT
    TRISAbits.TRISA2=1; // TRISA2(RA2) ANALOG POT, INPUT
    TRISAbits.TRISA4=1; // TRISA4(RA4) BIG LIGHT SWITCH, INPUT
    TRISAbits.TRISA5=1; // TRISA5(RA5) SMALL LIGHT SWITCH, INPUT
    ANSELAbits.ANSA2=1; // ANSELA2(ANSA2) ANALOG POT, INPUT ANALOG
    CCP1PPSbits.CCP1PPS=0b00000; // BIG LIGHT DRIVER (PWM->RA4), OUTPUT
    CCP2PPSbits.CCP2PPS=0b00001; // SMALL LIGHT DRIVER (PWM->RA5), OUTPUT
   
    ADCON0bits.CHS=0b000010; // ANALOG CHANNEL SELECTION BITS (RA2)
    ADCON1bits.ADCS=0b111; // ADC COVERSION CLOCK SELECTION BITS (ADCRC)
    ADCON0bits.ADON=1; // ANALOG CHANNEL SELECTION BITS (ADCON HIGH)
    ADCON1bits.ADPREF=0b00; //ADC POSITIVE VOLTAGE REFRENCE CONFIGRATION bits (VREF+ IS VDD)
    ADCON1bits.ADFM=1; // ADC RESULT FORMAT SELECTION BITS (RIGHT JUSTIFIED)
   
    BIG_SW=PORTAbits.RA4; //READ RA4 AND ASSIGN IT TO BIG_SW
    SMALL_SW=PORTAbits.RA5; //READ RA5 AND ASSIGN IT TO SMALL_SW
   
    PIE0bits.IOCIE=1;//INTERUPT-ON-CHANGE ENABLE BIT IS SET
    IOCANbits.IOCAN4=1;//INTERUPT-ON-CHANGE PORTA (RA4) NEGATIVE EDGE TRIGGERED
    IOCANbits.IOCAN5=1;//INTERUPT-ON-CHANGE PORTA (RA5) NEGATIVE EDGE TRIGGERED
   
    while(1)
    {
        while(BIG_SW==1||SMALL_SW==1)
        {
        PMD1bits.TMR2MD=0b0; // TIMER2 MOUDLE ENABLED
        T2CONbits.CKPS=0b000; //TIMER2 PRESCALER SET TO 1:1
        T2CONbits.OUTPS=0b0000; //TIMER2 POST-SCALER SET TO 1:1
        T2PRbits.T2PR=0b01100011;  // PR2 REGESTER SET TO 99
        T2CLKCONbits.CS=0b0011; // TIMER2 CLOCK SOURCE SELECT BIT (HFINTOSC)
       
        CCP1CONbits.CCP1FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)
        CCP1CONbits.CCP1MODE=0b1111; // MODE IS SET TO PWM
        CCP2CONbits.CCP2FMT=1; //CCPW PULSE WIDTH Alignment bit (RIGHT JUSTIFIED)
        CCP2CONbits.CCP2MODE=0b1111; // MODE IS SET TO PWM
       
        if(BIG_SW==1)
        {
            ADC_RESULT();
            CCPR1=RESULT;
            PIR4bits.TMR2IF=0b0;
            T2CONbits.T2ON=0b1;
        }
       
        if(SMALL_SW==1)
        {
            ADC_RESULT();
            CCPR2=RESULT;
            PIR4bits.TMR2IF=0b0;
            T2CONbits.T2ON=0b1;
        }
       
        }
        if (BIG_SW==0&&SMALL_SW==0)
        {
            SLEEP;
        }
   
   
    }
   
   
   
 
}
--- End code ---
the sleep thou gave me an error:

--- Code: ---main.c:130:13: error: use of undeclared identifier 'SLEEP'
--- End code ---

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod