Skip to content
Snippets Groups Projects
README.md 7.31 KiB
Newer Older
  • Learn to ignore specific revisions
  • Ruben Castro's avatar
    Ruben Castro committed
    # ATKITBreadboardTesting
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    PIDMotorControl Example includes code for DAC, ADC, PWM, Timer Interrupts, 
    PID, Current Control, Encoders w/ interrupts, pins, clock frequency setup, and low pass filters
    
    
    
    Ruben Castro's avatar
    Ruben Castro committed
    DAC()<< example in this code is meant only to use DACB due to poor construction
    Used to convert digital signals to analog signals - really useful for debugging on scopes
    
        DAC
        CTRLA - enable a channel on the DAC, and enable DAC
        CTRLB - set DAC to single channel use or dual channel use
        CTRLC - Set the reference voltage
        
        DAC Channel
        DACB.STATUS - used to check if its ready to convert again.
        DACx.CHyDATA - 12 bit value to output
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    ADC(ADC, ADC_CH, ADC_CH_MUXPOS);
    Pass in the ADC you want to use. channel, and the Pin you want to sue for POS side(NEG is gnd here)
    
    Ruben Castro's avatar
    Ruben Castro committed
    Used to convert Analog signals to digital signals for processing. (i.e. - current sensing)
    
    Ruben Castro's avatar
    Ruben Castro committed
    
        ADC can be setup in multiple ways- first divide being between single or differential mode
        In the example, it is setup in differential mode W gain.
        
        CTRLA enable ADC
        CTRLB ADC Resolution
        REFCTRL Ref voltage 
    
    Ruben Castro's avatar
    Ruben Castro committed
        PRESCALER ADC clock prescaler - ADC runs on its own clock- you want to make sure to run it down, otherwise you run into many problems.
        
        ADC Channel
        
    
    Ruben Castro's avatar
    Ruben Castro committed
        CTRL- channel input mode(DIFFWGAIN in this case) and the gain value, and to start a scan(1<<7)
        remember to check if scan is done being computed before doing again. Value 1<<7 is turned off 
        when scan is done
    
    Ruben Castro's avatar
    Ruben Castro committed
        MUXCTRL - setting the positive and negative pins.
    
    
    
    PWM(Timer, Prescalar, pwm channel, base frequency, desired frequency)
    For PWM, you have to setup multiple things. You are using the Timer on the chip,
    so you have to setup its period(compare capture value with MAX 65536), its prescalar,
    its mode, along with the channel at which to output when the timer hits the compare value.
    
        Necessary Registers to run minimal PWM
            Timer
            
            CTRLA - prescalar - use the minimum amount in order to preserve as much
            resolution as possible
            CTRLB - Timer mode (Singleslope for PWM-> TC_WGMODE_SINGLESLOPE_gc)
            and the pwm channel on which to output given as TCX_CCXEN_bm type
            PERBUFL & PERBUFH - Hi and lo period values for timer. Timer counts up to
            this value and then restarts back to 0.
            
        
            Timer Channel
            
            CCXBUFH & CCXBUFL - compare value. When the Timer hits this value on its
            count up, it will change the output to low.
            
    
    Ruben Castro's avatar
    Ruben Castro committed
    Timer Interrupts
    
    Ruben Castro's avatar
    Ruben Castro committed
    Also uses Timer (should be obvious given by name ;) ) 
    To set up, make sure that interrupts are enabled by including <avr/interrupt.h>,
    and calling sei(); and setting the PMIC CTRL pins to each level wanted 
    (high, medium, and/or low level interrupts)
    
    Remember to set the pin you want as an output using PORTX.DIRSET register
    
        Timer
        
        CTRLA - setup prescalar
        PERBUFL & PERBUFH - setup period same as PWM above
        INTCTRLA - initiate the interrupt
        
        then, add a method without return type(not even void) named ISR(TCCX_OVF_vect), 
        where X is your timer number with the contents that you want to loop over.
    
    
    PID(P,I,D, dt, CONT, MIN & MAX IN & OUT, K)
    Typical PID sequence, with some added features. enable CONT in order to have a loop
    for a system that is circular (i.e. a 360 degree arm yes vs a 1d elevator no)
    Setup mininum and maximum outputs, with integral portion not allowed to go over
    the MAX& MIN Outs. Since the derivative portion can be quite noisy run at a very
    fast frequency, a low pass filter is automatically applied to the D value,
    with K being a constant used to change the low pass filter's response time. See 
    
    Ruben Castro's avatar
    Ruben Castro committed
    low pass filter for details on that. dt is the period of each loop.(1second /frequency)
    
        crunch(input) logic
        current error = setpoint - current value<<<<<< this is changed if it is CONT. If CONT, find
        the shortest distance to setpoint is the current error.
        total error+= current error;
        derivate error = filter(current error - previous error)
        output = P* current error + I* total Error + D* derivative error
        
        onTarget() logic
        if on target according to acceptable range for more than a 
        certain amount of time, return true
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
        setAcceptableRange() logic
        set the acceptable range +- where range is sepoint+-acceptable range
        
        setSetpoint()
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
    Current Control(P, I, dt, MAX&MIN IN&OUT)
    Basic PI loop. I is used much more than normal, P being used for the initial ramp up.
    Same setup as PID loop, but without the derivative term
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
        crunch(input) logic
        current error = setpoint - current value
        the shortest distance to setpoint is the current error.
        total error+= current error;
        output = P* current error + I* total Error 
        
        onTarget() logic
        if on target according to acceptable range for more than a 
        certain amount of time, return true
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
        setAcceptableRange() logic
        set the acceptable range +- where range is sepoint+-acceptable range
        
        setSetpoint()
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
    Encoder w/ interrupts/ATKEncoder
    Encoders that automatically update based on interrupts running on a certain port.
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
        PORTX_DIRSET &= ~(PINx_bm | PINy_bm) - set the direction of the two input pins
        PORTX.INTCTRL - set the level of the interrupt(high/med/low)
        PORTX.INTzMASK= set the interrupt of the port towards a certain pin
        PORTX.PINxCTRL = set Pin to trigger on rising or falling edge 
        (make sure one interrupt is set on falling and other on rising edge)
        
        ISR(PORTX_INTz_vect) logic ( 1 for each pin used)
        if pins are different values, add to counter value, if pins are the same, subtract
        This is due to the nature of encoders and how they count. If running clockwise,
        the values line up, and if counter clockwise they dont line up(the values are 90 degrees away
        from each other)
        
    
    Ruben Castro's avatar
    Ruben Castro committed
    Basic Pin I/O
        PORTX_DIRSET - set the direction of each port- 0 for input 1 for output
        PORTX_DIRTGL - toggle direction 
        PORTX_DIRSET/CLR - set or clear direction of each port
        
        PORTX_OUTSET/TGL/CLR- set/toggle/clear output to high or low
        
    clock frequency setup
    Don't really understand this, just copy paste. Used to set clock to 48 Mhz
    
    	 OSC.XOSCCTRL = OSC_XOSCSEL_XTAL_256CLK_gc | OSC_FRQRANGE_12TO16_gc; // select external source
    	 OSC.CTRL = OSC_XOSCEN_bm; // enable external source
    	 while(!(OSC.STATUS & OSC_XOSCRDY_bm)); // wait for external
    	 OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | OSC_PLLFAC0_bm | OSC_PLLFAC1_bm; // select external osc for pll, do pll = source * 3
    	 //OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | OSC_PLLFAC1_bm; // pll = source * 2 for 32MHz std clock
    	 OSC.CTRL |= OSC_PLLEN_bm; // enable PLL
    	 while (!(OSC.STATUS & OSC_PLLRDY_bm)); // wait for PLL to be ready
    	 CCP = CCP_IOREG_gc; // enable protected register change
    	 CLK.CTRL = CLK_SCLKSEL_PLL_gc; // switch to PLL for main clock
     
     
    
    low pass filters(K)
    Used to clean a noisy signal. meant to be run at a fast frequency, since (1-2^-k)takes many
    clock counts to settle.
    Algorithm- output = y(n) = (1-2^-k)(y(n-1)) + (2^-k)(x(n)) << y(n) output, x(n)new input, n current clock count
    
        filter(input)
        give in new input, and returns in output
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    
    Ruben Castro's avatar
    Ruben Castro committed
    
    Currently two examples of working code using Atmel Studio
    for the Automota Kit Breadboard board
    
    DACExample
    Outputs a sine wave out of the PB2 port using DACB
    
    
    PWMControl
    Outputs a pwm signal ranging from 0-100% duty cycle at 20khz