5 Replies Latest reply on Jul 20, 2016 12:36 AM by H_E_L_P

    PWM to ESC

    antinnit

      Hi everyone!

       

      I'm looking into getting a brush-less motor to spin from my Edison using the Sparkfun PWM Block, from the PWM i'm linking over to a Simon 12A ESC to the Motor.

      I have connected all the parts up, putting the yellow/white receiver wire into the PWM Blocks SIG on CH0, I have then started on the MRAA code side in C++.

       

      My tests are bassed off (Georgi Todorov, PCA9685) stuff. So far I think the PWM Block is found and being written to (I get MRAA_SUCCESS returned).

       

      Here is my code so far (but no response form the ESC);

       

      #include <iostream>
      #include <string>
      
      
      #include <mraa.hpp>
      #include "Motor.h"
      
      
      using namespace std;
      
      
      mraa::I2c* i2c;
      mraa_result_t retval;
      
      
      void reset(void) {
        if (retval == MRAA_SUCCESS) i2c->writeReg(MODE1, 0x00); //Normal mode
        if (retval == MRAA_SUCCESS) i2c->writeReg(MODE2, 0x04); //totem pole
        cout << "reset out: " << retval << endl;
      }
      
      
      void setPWMFreq(int freq) {
        uint8_t prescale_val = (CLOCK_FREQ / 4096 / freq) - 1;
        if (retval == MRAA_SUCCESS) retval = i2c->writeReg(MODE1, 0x10); //sleep
        if (retval == MRAA_SUCCESS) retval = i2c->writeReg(PRE_SCALE, prescale_val); // multiplyer for PWM frequency
        if (retval == MRAA_SUCCESS) retval = i2c->writeReg(MODE1, 0x80); //restart
        if (retval == MRAA_SUCCESS) retval = i2c->writeReg(MODE2, 0x04); //totem pole (default)
        cout << "setPWMFreq out: " << retval << endl;
      }
      
      
      void setPWM(uint8_t target, int value) {
        setPWM(target, 0, value); // value 0 - 4095. More like value (0 - 3838)
      }
      
      
      void setPWM(uint8_t target, int on_value, int off_value) {
        i2c->writeReg(LED0_ON_L + LED_MULTIPLYER * (target - 1), on_value & 0xFF);
        i2c->writeReg(LED0_ON_H + LED_MULTIPLYER * (target - 1), on_value >> 8);
        i2c->writeReg(LED0_OFF_L + LED_MULTIPLYER * (target - 1), off_value & 0xFF);
        i2c->writeReg(LED0_OFF_H + LED_MULTIPLYER * (target - 1), off_value >> 8);
      }
      
      
      int getPWM(uint8_t led){
        int ledval = 0;
        ledval = i2c->readReg(LED0_OFF_H + LED_MULTIPLYER * (led - 1));
        ledval = ledval & 0xf;
        ledval <<= 8;
        ledval += i2c->readReg(LED0_OFF_L + LED_MULTIPLYER * (led - 1));
        return ledval;
      }
      
      
      void setAllPWM(int last, int value) {
        for (int ii = 0; ii < last; ii++) {
        uint8_t t = ii;
        setPWM(t, 0, value);
        }
      }
      
      
      int main()
      {
        cout << "--Motors----------------------------------" << endl;
      
      
        i2c = new mraa::I2c(1);
        cout << i2c << endl;
        retval = i2c->address(0x40);
        cout << "address:" << retval << endl;
      
      
        if (retval == MRAA_SUCCESS) {
        setPWMFreq(400);
        reset();
        setPWM(0, 700); // read this does something (but nope)
        int data = getPWM(0);
        cout << "-- data:" << data << endl;
        setPWM(0, 2000); // maybe this? nope also
        data = getPWM(0);
        cout << "-- data:" << data << endl;
        } else {
        cout << "failed:" << endl;
        }
      
      
        cout << "exiting Motors" << endl;
        while (1) {}
      
      
        return 0;
      }
      

       

      With a simpler header of:

       

      #include <mraa.hpp>
      
      
      #define MODE1 0x00 //Mode  register  1
      #define MODE2 0x01 //Mode  register  2
      #define SUBADR1 0x02 //I2C-bus subaddress 1
      #define SUBADR2 0x03 //I2C-bus subaddress 2
      #define SUBADR3 0x04 //I2C-bus subaddress 3
      #define ALLCALLADR 0x05     //LED All Call I2C-bus address
      #define LED0 0x6 //LED0 start register
      #define LED0_ON_L 0x6 //LED0 output and brightness control byte 0
      #define LED0_ON_H 0x7 //LED0 output and brightness control byte 1
      #define LED0_OFF_L 0x8 //LED0 output and brightness control byte 2
      #define LED0_OFF_H 0x9 //LED0 output and brightness control byte 3
      #define LED_MULTIPLYER 4 // For the other 15 channels
      #define ALLLED_ON_L 0xFA    //load all the LEDn_ON registers, byte 0 (turn 0-7 channels on)
      #define ALLLED_ON_H 0xFB //load all the LEDn_ON registers, byte 1 (turn 8-15 channels on)
      #define ALLLED_OFF_L 0xFC //load all the LEDn_OFF registers, byte 0 (turn 0-7 channels off)
      #define ALLLED_OFF_H 0xFD //load all the LEDn_OFF registers, byte 1 (turn 8-15 channels off)
      #define PRE_SCALE 0xFE //prescaler for output frequency
      #define CLOCK_FREQ 8000 //8kHz default emax esc clock
      
      
      void setPWMFreq(int);
      void setPWM(uint8_t, int, int);
      void setPWM(uint8_t, int);
      int getPWM(uint8_t);
      void setAllPWM(int, int);
      

       

      I don't now much in regards to arming the ESC or if the Frequencies are setup correctly, just randomly trying stuff at this point.

      Any help would be great, fun stuff, love to get me motor spinning.

        • 1. Re: PWM to ESC
          antinnit

          I fixed it, it was the channel, all the rest works.

           

          If anyone wants to use, just setPWM(1, 120) instead of setPWM(0, 120). its always something simple.

          I set my hz to 50, but can be whatever your ESC needs.

          • 2. Re: PWM to ESC
            John_Quin

            This is going to be of huge help to me. Thanks for the post

            • 3. Re: PWM to ESC
              JTilghman

              Trying to get this block to work as well, what is needed to be installed to compile this code ?

              • 4. Re: PWM to ESC
                H_E_L_P

                Thanks for this. Got this working for the Sparkfun PWM block in Python.

                 

                 

                • 5. Re: PWM to ESC
                  H_E_L_P

                  Its very speggetti... sorry in advance

                   

                  from __future__ import division
                  import mraa
                  import time

                  #Contant Values
                  MODE1 = 0x00
                  MODE2 = 0x01
                  SUBADR1 = 0x02
                  SUBADR2 = 0x03
                  SUBADR3 = 0x04
                  ALLCALLADR = 0x05
                  LED0 = 0x6
                  LED0_ON_L = 0x06
                  LED0_ON_H = 0x07
                  LED0_OFF_L = 0x8
                  LED0_OFF_H = 0x9
                  LED1_ON_L = 0x10
                  LED1_ON_H = 0x11
                  LED1_OFF_L = 0x12
                  LED1_OFF_H = 0x13
                  LED2_ON_L = 0x14
                  LED2_ON_H = 0x15
                  LED2_OFF_L = 0x16
                  LED2_OFF_H = 0x17
                  LED3_ON_L = 0x18
                  LED3_ON_H = 0x19
                  LED3_OFF_L = 0x20
                  LED3_OFF_H = 0x21
                  LED_MULTIPLIER = 4
                  ALLLED_ON_L = 0xFA
                  ALLLED_ON_H = 0xFB
                  ALLLED_OFF_L = 0xFC
                  ALLLED_OFF_H = 0xFD
                  PRE_SCALE = 0xFE
                  CLOCK_FREQ = 25000000

                  x = mraa.I2c(1) # Define I2c object on bus (0-6)?
                  print('x')
                  print(x)
                  x.address(0x40) # Define Address of PCA9685 PWM BLOCK (Default = 0x40)
                  print('x.address:')
                  print(x.address)

                  #retval = x.result_t
                  #print(retval)

                  if x.readReg(0xd0) != 0x55: #Initialize the device
                      print("error") # print error statement
                      print('error returned:')
                      print(x.readReg(0xd0))
                     
                  def bytes(num):
                      print('num:')
                      print(num)
                      if len(num)-2 < 3:
                          low = num
                          high = hex(0)
                      elif len(num)-2 == 3:
                          high = str("0x0" + num[2:3])
                          low = str("0x" + num[3:5])
                          print('high,low')
                          print(high)
                          print(low)
                      return high,low
                     
                  def reset():
                      x.writeReg(MODE1, 0x10)
                      #x.writeReg(PRE_SCALE, prescale_val)
                      x.writeReg(PRE_SCALE, 0x0e) #multiplier for PWM freq
                      x.writeReg(MODE1, 0x80)
                      x.writeReg(MODE2, 0x04)

                  def setPWMFreq(freq):
                      freq = int(freq)
                      #prescale_val = hex((CLOCK_FREQ/4096/freq)-1)
                      prescale_val = hex(int((CLOCK_FREQ/4096/freq)-1))
                      print('prescale')
                      print(prescale_val)
                      x.writeReg(MODE1,0x10) #sleep
                      #x.writeReg(PRE_SCALE,prescale_val) #multiplier for PWM freq
                      x.writeReg(PRE_SCALE,0x0e) #multiplier for PWM freq
                      x.writeReg(MODE1,0x80) #restart
                      x.writeReg(MODE1,0x04) #totem pole (default)
                     
                  def setPWM(target,value):
                      #target = hex(target)
                      print('target')
                      print(target)
                      value = int(value)
                      print('value')
                      print(value)
                      setPWMM(target,hex(0),hex(value)) #value 0 - 4095. More like value (0 - 3838)


                  def setPWMM(target,on_value,off_value):
                  ##    print('on_value')
                  ##    print(on_value)
                  ##    print('off_value')
                  ##    print(off_value)
                      high_on, low_on = bytes(on_value)
                      high_off, low_off = bytes(off_value)
                      high_on = int(high_on,16)
                      low_on = int(low_on,16)
                      high_off = int(high_off,16)
                      low_off = int(low_off,16)

                  ##    print('low_on')
                  ##    print(low_on)
                  ##    print('high_on')
                  ##    print(high_on)
                  ##    print('low_off')
                  ##    print(low_off)
                  ##    print('high_off')
                  ##    print(high_off)

                      motor1.writeReg(LED0_ON_L + 4*(target - 1),low_on)
                      motor1.writeReg(LED0_ON_H + 4*(target - 1),high_on)
                      motor1.writeReg(LED0_OFF_L + 4*(target - 1),low_off)
                      motor1.writeReg(LED0_OFF_H + 4*(target - 1),high_off)


                  def getPWM(led):
                      #led = hex(led)
                      ledval = int(0)
                      ledval = x.readReg(LED0_OFF_H + LED_MULTIPLIER * (led -1))
                      ledval = ledval & 0xf
                      ledval <<= 8
                      ledval += x.readReg(LED0_OFF_L + LED_MULTIPLIER * (led-1))
                      return ledval

                  counter = 0
                  retval = x.address(0x40)
                  setPWMFreq(50)
                  setPWM(1,1000)
                  time.sleep(3)

                  ## Note here 2000 is zero throttle and 4000 is full throttle
                      retval = x.address(0x40)
                      print('retval:')
                      print retval
                     
                  # A loop used to test some functions.
                  while counter < 1:

                     

                      counter = counter + 1
                      print('counter:')
                      print(counter)
                      setPWMFreq(50) # 50Hz
                      reset()
                      setPWM(1,2000)
                      data = getPWM(1)
                      print('getPWM:')
                      print(data)
                      time.sleep(3)
                      setPWM(1,2500)
                      data = getPWM(1)
                      print('getPWM:')
                      print(data)
                      time.sleep(3)
                     
                      time.sleep(3)
                      setPWM(1,2000)
                      data = getPWM(1)
                      print('getPWM:')
                      print(data)
                      time.sleep(3)
                     
                      print('PRE_SCALE')
                      print(x.readReg(PRE_SCALE))
                      print('MODE1')
                      print(x.readReg(MODE1))
                      print('MODE2')
                      print(x.readReg(MODE2))
                      print('LED0_ON_L')
                      print(x.readReg(LED0_ON_L))
                      print('LED0_ON_H')
                      print(x.readReg(LED0_ON_H))
                      print('LED0_OFF_L')
                      print(x.readReg(LED0_OFF_L))
                      print('LED0_OFF_H')
                      print(x.readReg(LED0_OFF_H))
                      print('-------NEXT LINE --------')