Shop OBEX P1 Docs P2 Docs Learn Events
Automatic motor tuner (Newbie) — Parallax Forums

Automatic motor tuner (Newbie)

mnemonicsmnemonics Posts: 23
edited 2014-01-20 13:55 in Propeller 1

Hello all, I am new to spin and I am trying to come up with an automatic motor tuner code but don't know where to start..
I wanted to increment frequencies starting from 1 hz and up to it reaches max current. I was going to use the Sigma/Delta A/D code but don’t know if it will be better than using the ADC0831 or the MCP3208.

Then I read that the MCP3208 is better and easier to implement than the ADC0831 because I would have to add components to that chip to make it work with the Prop . The current sensor I am using is an ACS712ELCTR-30A which puts out about .66mA per Amp. I was planning on incrementing the output freq and or maybe use PWM to look for the max val and set it there.
. I wanted the prop to ramp up from zero and look for the most efficient setting and lock on to it. I looked at a lot of demo codes and was planning on using the MCP3208 code to do the A/D conversion but I don’t know how to start or how to make the prop start the Freq out and look at the MCP3208 max Val and set it there.
I am going to use the LCD Obj code to look at what it did and display it to my LCD. I think I can tie the rest of it together or I will try too, but don’t know how to start the freq out or the PWM out and increment it . I looked at the incrementunitlcondition Obj and ButtonShiftSpeed.spin I can get an LED light to increment the pulses but I have it set up to look at a button and stop incrementing when it the button goes high. That’s about as far as I got. I have a Prop Demo Board and a Quick Start board but most of the code samples are for the BOE…. Thanks in advance..

Comments

  • Mark_TMark_T Posts: 1,981
    edited 2014-01-14 17:12
    You can use DDS and sine-table lookup to get your sample values at some suitable sampling rate, how you do the D->A
    conversion is a separate issue. The Prop counter units do DDS for you for free in steps of 0.0186265 Hz (assuming
    80MHz system clock).
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-01-14 20:24
    You didn't mention what sort of motor or motor controller you're planning on using.

    I know from experience different motor controllers do well at different PWM frequencies.

    I think I posted a version of my PWM and encoder software which allows one to adjust the PWM frequency on the fly in this thread. The PWM generation doesn't use the counters so you wouldn't be able to use it at very high frequencies.

    I'm using a MCP3208 with the MC33926 motor controller to monitor current levels. The MCP3208 can be used with the Propeller just fine. If you use the MCP3208 at 5V you'll want to include a 10K ohm resistor between the chip's output and the Prop to protect the Prop from the 5V logic level. The MCP3208 can also be powered by 3.3V in which case you wouldn't need to worry about the logic differences.
  • mnemonicsmnemonics Posts: 23
    edited 2014-01-17 20:27
    {{ Using A Prop Starter Kit Board and a MCP3208 with Pin out as follows
    4 Wire 8 Channel single ended inputs
    3v3- MCP3208
     VDD
    ┌─────────────────┐ │
    ch0 ────┤1 CH0 VDD 16├──┫
    ch1 ────┤2 CH1 VREF 15├──┘
    ch2 ────┤3 CH2 AGND 14├──┐
    ch3 ────┤4 CH3 CLK 13├──│── clk
    pin 2 on prop
    ch4 ────┤5 CH4 DOUT 12├──│──-> -pin
    pin 3 on prop
    ch5 ────┤6 CH5 DIN 11├──│────── dio -- pin 4 on Prop
    ch6 ────┤7 CH6 /CS 10├──│──────── cs1 pin 5 on Prop
    ch7 ────┤8 CH7 DGND 9├──┫
    └─────────────────┘ │

    }}
    CON
    '' MCP3208 - ADC code snippet demo **********************************
    '>>> READ THE MCP3208 DATA SHEET CAREFULLY for correct SPI timing pulses
    '' Declare Objects & Variables
    _clkmode = xtal1 + pll16x 'PLL Multiplier
    _xinfreq = 5_000_000 'XTAL Frequency
    ''On Propeller Board On MCP3208 ic
    ''Symbol Pin I/O Function Symbol Pin I/O Function
    sdi = 3 'Data in <-- SDO 12 Out Serial Data Output/SPI default
    sdo = 4 'Data out --> SDI 11 In Serial Data Input /SPI default
    clk = 2 'Clock out --> CLK 13 In SerialClock Input /SPI default
    cs1 = 5 'CS out --> CS1 10 In Chip Select Input /Analog-Digital Converter







    OBJ
    DEBUG : "FullDuplexSerial" 'add this in the same directory


    VAR
    LONG ii, jj, command, channel, ADCvalue
    Byte LED, pulses


    PUB Main
    dira[sdi] := 0 'setSDI pin = input
    outa[sdo] := 0 'setSDO output = low
    dira[sdo] := 1 'setSDO pin = output
    outa[clk] := 0 'setCLK output = low
    dira[clk] := 1 'setCLK pin = output
    outa[cs1] := 1 'setCS output = high = deselect chip
    dira[cs1] := 1 'setCS pin = output ADC chip CS

    DEBUG.start(31, 30, 0, 115200) 'start Full Duplex Serial DEBUG
    waitcnt(clkfreq + cnt)
    DEBUG.str(string(1, "Start MCP3208 8-Channel ADC ", 13 ))
    REPEAT
    DEBUG.tx(0 ) 'clear serial terminal screen (0 )
    ii++
    DEBUG.str(string("Cnt# = "))
    DEBUG.dec( ii )
    DEBUG.tx(13)
    repeat jj from 0 to 7
    DEBUG.tx(11 )
    DEBUG.str(string(" Ch"))
    DEBUG.dec(jj)
    DEBUG.str(string(" val = "))
    DEBUG.dec( ADC3208(jj) ) 'get ADC value (channel)
    DEBUG.tx(13)
    waitcnt(clkfreq/8 + cnt)


    PUB ADC3208(chan) 'get ADC voltage value
    channel := chan 'save "channel"variable
    outa[cs1] := 1 'Set CS1 output= high - preset value
    outa[clk] := 1 'Set CLK output= high - preset clock pulse bf CS2
    outa[cs1] := 0 'CS1 output low - start ADC
    outa[clk] := 0 '>>> READ THE MCP3208 DATA SHEET CAREFULLY <<<
    command :=(%11000 + chan) << (32-5) 'command Start, Single, Chan(xx)
    repeat 5 'send 5 command bits - per Specification
    outa[sdo] := (command <-= 1) & 1
    outa[clk] := 1 'clock the command bit
    outa[clk] := 0
    outa[clk] := 1 'set CLK output= high - one clock pulse after Command = 5th Clock pulse
    outa[clk] := 0 'set CLK output= low - set sample and hold ADC value
    outa[clk] := 1 'set CLK output= high - one clock pulse after Command = 6th Clock pulse
    outa[clk] := 0 'set CLK output= low - end conversion = Null bit
    ADCvalue := 0 'clear work variable =0
    repeat 12 'read conversion 12 data bits
    ADCvalue := (ADCvalue << 1) | ina[sdi] 'input ADC data bit
    outa[clk] := 1 'clock ADC data bit
    outa[clk] := 0
    outa[clk] := 0 'just to be sure = 0
    outa[cs1] := 1 'CS1 output high - end ADC
    outa[clk] := 0
    return ADCvalue


    pub scale(value, outmin, outmax)


    '' Scales raw (0 to 4095) value to new range: outmin to outmax


    value := 0 #> value <# 4095 ' constrain input


    return map(value, 0, 4095, outmin, outmax) ' scale to new range




    pub map(value, inmin, inmax, outmin, outmax)


    '' Maps value in range inmin..inmax to new value in range outmin..outmax
    '' -- liberated from Arduino library
    '' -- caution: no bounds checking


    return (value - inmin) * (outmax - outmin) / (inmax - inmin) + outmin


    {{ eventually i want to use the Amp sesnor value to increment and decrement the pulses
    but i can figure out how to even pulse the led. If i copy the section of code and program
    prop by itself it works but not with all this other code..}}


    PUB LEDpulses
    dira[16] ~~ 'set pin 16 led to output

    pulses := 5


    repeat

    if LED == 0
    LED := %10
    !outa[16] 'using pin 1 as input to increment pulses when high
    if ina[1] == 1 ' using pin 1 as input to decrement pulses when low
    pulses ++
    pulses <#= 254
    elseif ina[1] == 0
    pulses --
    pulses #>= 1


    waitcnt(clkfreq/pulses + cnt)
    outa[16] := LED
    LED >>= 1




    ' End of demo


    Thanks for the reply Mark and Duane
    I am using a Mosfet to drive the motor and not going through a MC33926. Also it won’t be at high frequencies either or at least I don’t think it will get high. I figured out how to set up the pins finally and I have the code working and the debug terminal but I am trying to flash an LED on pin 16 and the LED wont flash. The code by itself will increment pulses if the input goes high or decrement when low on pin 1. But when I pasted the code together the led does not work. Do I need to use another cog and if so how do I turn on another cog to run that piece of code? Eventually I think I can use JM piece of code to scale the A/D and then use the value to increment or decrement by itself but I can’t get past the LED just flashing right now. I only started with Spin a few weeks ago. Thanks..MCP3208_With Diagramand Debug terminal (1).spin
  • mnemonicsmnemonics Posts: 23
    edited 2014-01-17 20:45
    Sorry Guys ..I read my post and wanted to explain it better. The last section of code that pulses the LED light on pin 16 does not work. When I copied and pasted the PUB LEDpulses section the Led does not blink. If I open a new file a paste the code by itself it flashes the Led like it suppose to.
    PUB LEDpulses dira[16] ~~ 'set pin 16 led to output

    pulses := 5
    repeat

    if LED == 0
    LED := %10
    !outa[16] 'using pin 1 as input to increment pulses when high
    if ina[1] == 1 ' using pin 1 as input to decrement pulses when low
    pulses ++
    pulses <#= 254
    elseif ina[1] == 0
    pulses --
    pulses #>= 1


    waitcnt(clkfreq/pulses + cnt)
    outa[16] := LED
    LED >>= 1
    It works by itself but not with all the other codes snippets with it..
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-01-18 10:41
    The method "LEDpulses" is not called from anywhere within the code so it never starts. To run a method in a new cog you need to use the cognew statement.

    There are tutorials inside the Propeller Tool's help menu. If you work through the Propeller Education Kit (available in help menu) it will explain about running a method in a new cog.

    In order to post code to the forum you need to use code tags (not quotes).

    Here's a link to a tutorial on posting code.

    attachment.php?attachmentid=78421&d=1297987572
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-01-19 07:00
    I posted a LED blinking program a while back which uses cognew to start a cog to control the LEDs. Hopefully it will be instructive.

    There's also an appnote on starting new cogs. Unfortunately there was a bug in the code. Hopefully Parallax has fixed the bug. I couldn't find the appnote I was thinking of but #11 does show how to use cognew.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2014-01-19 18:33
    Hi mnemonics;

    What kind or type of motor are you using?
    Is it a stepper motor?
    or is it a
    Permanent magnet DC motor?

    Duane J
  • mnemonicsmnemonics Posts: 23
    edited 2014-01-19 23:31
    Duane I am using a DC motor with variable loads. The load will change and I may also drive other Coils with it. Just want to see if the Prop can look at A/D Value and increment pulses till it gets to best setting. Don't want to overdrive a coil past saturation.. I have three codes that I have been trying to use but I don't know how to put them together to make the whole thing work .. Thanks...
  • mnemonicsmnemonics Posts: 23
    edited 2014-01-20 12:47
    {{ 
     
       Using A Prop Starter Kit Board and a MCP3208 with Pin out as follows
         4 Wire 8 Channel single ended inputs
                                    3v3- MCP3208
                                      &#61463; VDD
                 &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;  &#9474;
        ch0 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;1  CH0     VDD 16&#9500;&#9472;&#9472;&#9515;                
        ch1 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;2  CH1    VREF 15&#9500;&#9472;&#9472;&#9496;           
        ch2 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;3  CH2    AGND 14&#9500;&#9472;&#9472;&#9488; 
        ch3 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;4  CH3     CLK 13&#9500;&#9472;&#9472;&#9474;&#9472;&#9472;&#61626; clk--------pin 2 on prop
        ch4 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;5  CH4    DOUT 12&#9500;&#9472;&#9472;&#9474;&#9472;&#9472;-> -pin------pin 3  on prop
        ch5 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;6  CH5     DIN 11&#9500;&#9472;&#9472;&#9474;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#61626; dio -- pin 4 on Prop
        ch6 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;7  CH6     /CS 10&#9500;&#9472;&#9472;&#9474;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#61626;&#9472; cs1  pin 5 on Prop             
        ch7 &#9472;&#61627;&#9472;&#9472;&#9472;&#9508;8  CH7    DGND  9&#9500;&#9472;&#9472;&#9515;
                 &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;  &#9474;
                                      &#61464;
       }}
    CON 
      '' MCP3208 - ADC code snippet demo **********************************
    '>>>  READ THE MCP3208 DATA SHEET CAREFULLY for correct SPI timing pulses
    '' Declare Objects & Variables  
      _clkmode      = xtal1 + pll16x    'PLL Multiplier
      _xinfreq      = 5_000_000         'XTAL Frequency  
    ''On Propeller Board                 On MCP3208 ic 
    ''Symbol    Pin I/O   Function       Symbol Pin I/O  Function 
      sdi           = 3  'Data  in   <-- SDO  12  Out Serial Data Output/SPI default  
      sdo           = 4  'Data  out  --> SDI  11  In  Serial Data Input /SPI default 
      clk           = 2  'Clock out  --> CLK  13  In  SerialClock Input /SPI default
      cs1           = 5  'CS    out  --> CS1  10 In  Chip Select Input /Analog-Digital Converter
    OBJ
      DEBUG  : "FullDuplexSerial"       'add this in the same directory 
      
     LEDs1 : "2 ButtonShiftSpeedtest"
      
    VAR
      LONG ii, jj, command, channel, ADCvalue 
      Byte LEDS, PULSES                        
    
    
    PUB Main
    
    
      
      dira[sdi]    := 0  'setSDI pin    = input   
      outa[sdo]    := 0  'setSDO output = low 
      dira[sdo]    := 1  'setSDO pin    = output
      outa[clk]    := 0  'setCLK output = low 
      dira[clk]    := 1  'setCLK pin    = output
      outa[cs1]    := 1  'setCS  output = high = deselect chip
      dira[cs1]    := 1  'setCS  pin    = output ADC chip CS
    
    
      
     DEBUG.start(31, 30, 0, 115200)     'start Full Duplex Serial DEBUG
      waitcnt(clkfreq + cnt)     
      DEBUG.str(string(1, "Start MCP3208 8-Channel ADC ", 13 ))  
      REPEAT
        DEBUG.tx(0 )                     'clear serial terminal screen (0 )
        ii++
        DEBUG.str(string("Cnt# = "))
        DEBUG.dec( ii )
        DEBUG.tx(13)
        repeat jj from 0 to 7
           DEBUG.tx(11 )                 
           DEBUG.str(string("  Ch"))
           DEBUG.dec(jj)
           DEBUG.str(string(" val = "))
           DEBUG.dec( ADC3208(jj) )      'get ADC value (channel)
           DEBUG.tx(13)
           waitcnt(clkfreq/8 + cnt)
    
    
                
    PUB ADC3208(chan)           'get ADC voltage value   
      channel      := chan      'save "channel"variable
      outa[cs1]    := 1         'Set CS1 output= high - preset value
      outa[clk]    := 1         'Set CLK output= high - preset clock pulse bf CS2
      outa[cs1]    := 0         'CS1 output low - start ADC  
      outa[clk]    := 0         '>>>  READ THE MCP3208 DATA SHEET CAREFULLY <<<-----------------------
      command      :=(%11000 + chan) << (32-5)  'command Start, Single, Chan(xx)
      repeat 5                  'send 5 command bits - per Specification
         outa[sdo] := (command <-= 1) & 1           
         outa[clk] := 1         'clock the command bit
         outa[clk] := 0
      outa[clk]    := 1         'set CLK output= high - one clock pulse after Command = 5th Clock pulse 
      outa[clk]    := 0         'set CLK output= low  - set sample and hold ADC value
      outa[clk]    := 1         'set CLK output= high - one clock pulse after Command = 6th Clock pulse 
      outa[clk]    := 0         'set CLK output= low  - end conversion = Null bit 
      ADCvalue     := 0         'clear work variable =0  
      repeat 12                 'read conversion 12 data bits                                        
         ADCvalue  := (ADCvalue << 1) | ina[sdi] 'input ADC data bit
         outa[clk] := 1         'clock ADC data bit
         outa[clk] := 0
      outa[clk]    := 0         'just to be sure = 0
      outa[cs1]    := 1         'CS1 output high - end ADC
      outa[clk]    := 0                       
      return ADCvalue
    
    
    
    
    PUB ShiftLedsLeft
     dira[16..23] ~~
        
        PULSES := 5
    
    
         repeat
           
           if LEDS == 0
              LEDS := %1000
           !outa[20..23] 
            
                    
           if ina[0] == 1
              PULSES ++
              PULSES <#= 254
           elseif ina[0] == 0
              PULSES --
              PULSES #>= 1
    
    
           waitcnt(clkfreq/PULSES + cnt)
           outa[16..19] := LEDS 
           outa[20..23] := LEDS
           LEDS >>= 1          
     
    
    Ok so I still can't get the leds to Pulse.. I put the Obj in for the LED code and I thought i called it but it still does not work. I looked at samples but can't figure out why everything is working but the LEDS. If I put the code in the beginning the LEDS flash but the terminal does not work. .. What am I doing wrong..
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-01-20 13:55
    You need to assign stack space to use with your "ShiftLedsLeft" method and call "ShiftLedsLeft" with cognew. The appnote I linked to in post #7 shows you how to do both of these.
Sign In or Register to comment.