servo control on beaglebone blue

Hello,
I am currently working on beaglebone blue and I am trying to control the servo using the servo motor pins on the beaglebone blue in channel 1. My servo is moving fine when I give command
rc_test_servos -c 1 -w 1100 and like that I change the value to 1900 gradually with difference of 100.
But now I am trying to write a code in the servo can move automatically from 1100 to 1900 or in position -90 degrees to + 90 degrees continuosly with some delay between each intervals when I run the code.
Do any have any Idea on this please let me know.

Thanks
Laasya

https://docs.beagleboard.org/latest/books/beaglebone-cookbook/04motors/motors.html#controlling-a-servo-motor

This is helpful thanks a lot.

1 Like

Hi, I am trying to enable the PWM line by and identifying the channel the PWM is going to in beagle bone blue. I have already exported the PWM and have given the duty cycle, period and required data but I am having trouble in finding the channel in which the data is going in Beagle Bone Blue.
Do you have any idea on this please let me know.

Thanks
Laasya

Hello @laasyapriya ,

/dev/bone/pwm/ should be the PWM channels available on the BBBlue if you are using a particular beagleboard.org image.

Can you give the output of these commands?

  1. uname -r
  2. cat /etc/dogtag

Either the channels are in /dev/bone/pwm/ or /sys/class/pwm/.

Either way, or if they are in /dev/pwm/, I think writing a template should help in this context.

librobotcontrol is a good library. I will research it again and see how far I get

Seth

P.S. I think making a template may help.

Okay…

Update

I think the interface(s) for handling the Servo Headers onboard the BBBlue w/ the librobotcontrol lib. is listed here: Robot Control Library: rc_test_servos.c . So, actually…

  1. The PRU controls the DRM. I will need to read more. It may take time.
  2. Sweeping back and forth may be done by controlling the source in the template from -1 to 1.
  3. I am not too familiar w/ PRUs or DRM.

Another person may want to jump in here. I am sorry.

Also @laasyapriya ,

Are you using librobotcontrol? I kind of jumped to conclusions here…

If you are using librobotcontrol, reading about the librobotcontrol various dsm and drm source may provide valuable ideas.

https://beagleboard.org/static/librobotcontrol/examples.html

The examples and the template(s) may help you.

I see there are ideas for the servos in the all of the dsm categories and examples.

 -s {limit}     Sweep servo back/forth between +- limit

So, use the -s argument for sweeping.

sudo rc_test_servos -c 1 -s 1.4 0.0

On my machine, this should sweep the servo back and forth but it does not. So, I think I am doing something wrong. It must need to be calibrated first.

I will keep testing and try to come up w/ some source soon.

/**
 * @file rc_project_template.c
 *
 * This is meant to be a skeleton program for Robot Control projects. Change
 * this description and file name before modifying for your own purpose.
 */

#include <stdio.h>
#include <robotcontrol.h> // includes ALL Robot Control subsystems

// function declarations
void on_pause_press();
void on_pause_release();


/**
 * This template contains these critical components
 * - ensure no existing instances are running and make new PID file
 * - start the signal handler
 * - initialize subsystems you wish to use
 * - while loop that checks for EXITING condition
 * - cleanup subsystems at the end
 *
 * @return     0 during normal operation, -1 on error
 */
int main()
{
	// make sure another instance isn't running
	// if return value is -3 then a background process is running with
	// higher privaledges and we couldn't kill it, in which case we should
	// not continue or there may be hardware conflicts. If it returned -4
	// then there was an invalid argument that needs to be fixed.
	if(rc_kill_existing_process(2.0)<-2) return -1;

	// start signal handler so we can exit cleanly
	if(rc_enable_signal_handler()==-1){
		fprintf(stderr,"ERROR: failed to start signal handler\n");
		return -1;
	}

	// initialize pause button
	if(rc_button_init(RC_BTN_PIN_PAUSE, RC_BTN_POLARITY_NORM_HIGH,
						RC_BTN_DEBOUNCE_DEFAULT_US)){
		fprintf(stderr,"ERROR: failed to initialize pause button\n");
		return -1;
	}

	// Assign functions to be called when button events occur
	rc_button_set_callbacks(RC_BTN_PIN_PAUSE,on_pause_press,on_pause_release);

	// make PID file to indicate your project is running
	// due to the check made on the call to rc_kill_existing_process() above
	// we can be fairly confident there is no PID file already and we can
	// make our own safely.
	rc_make_pid_file();


	printf("\nPress and release pause button to turn green LED on and off\n");
	printf("hold pause button down for 2 seconds to exit\n");

	// Keep looping until state changes to EXITING
	rc_set_state(RUNNING);
	while(rc_get_state()!=EXITING){
		// do things based on the state
		if(rc_get_state()==RUNNING){
			rc_led_set(RC_LED_GREEN, 1);
			rc_led_set(RC_LED_RED, 0);
		}
		else{
			rc_led_set(RC_LED_GREEN, 0);
			rc_led_set(RC_LED_RED, 1);
		}
		// always sleep at some point
		rc_usleep(100000);
	}

	// turn off LEDs and close file descriptors
	rc_led_set(RC_LED_GREEN, 0);
	rc_led_set(RC_LED_RED, 0);
	rc_led_cleanup();
	rc_button_cleanup();	// stop button handlers
	rc_remove_pid_file();	// remove pid file LAST
	return 0;
}


/**
 * Make the Pause button toggle between paused and running states.
 */
void on_pause_release()
{
	if(rc_get_state()==RUNNING)	rc_set_state(PAUSED);
	else if(rc_get_state()==PAUSED)	rc_set_state(RUNNING);
	return;
}

/**
* If the user holds the pause button for 2 seconds, set state to EXITING which
* triggers the rest of the program to exit cleanly.
**/
void on_pause_press()
{
	int i;
	const int samples = 100; // check for release 100 times in this period
	const int us_wait = 2000000; // 2 seconds

	// now keep checking to see if the button is still held down
	for(i=0;i<samples;i++){
		rc_usleep(us_wait/samples);
		if(rc_button_get_state(RC_BTN_PIN_PAUSE)==RC_BTN_STATE_RELEASED) return;
	}
	printf("long press detected, shutting down\n");
	rc_set_state(EXITING);
	return;
}

This is the template that I was describing from the library of librobotcontrol.

So, this should give some ideas on how to build your own. I will keep on it! Good luck!


Kernel: 5.10.162-ti-r58
BeagleBoard.org Debian Bullseye IoT Image 2022-11-01
Debian: 11.6

PASSED: gpio 0
PASSED: gpio 1
PASSED: gpio 2
PASSED: gpio 3
ERROR:  ti-pwm driver not loaded for hrpwm0
ERROR:  ti-pwm driver not loaded for hrpwm1
ERROR:  ti-pwm driver not loaded for hrpwm2
ERROR:  ti-eqep driver not loaded for eqep0
ERROR:  ti-eqep driver not loaded for eqep1
ERROR:  ti-eqep driver not loaded for eqep2
PASSED: pru-rproc
ERROR:  uart1 driver not loaded
ERROR:  uart2 driver not loaded
ERROR:  uart4 driver not loaded
ERROR:  uart5 driver not loaded
ERROR:  i2c1 driver not loaded
PASSED: i2c2
ERROR: spi driver not loaded
PASSED: LED
PASSED: ADC iio

Currently running on a:
MODEL_BB_BLUE
Robot Control library Version:
1.0.5

These are my passed/error output for the modules w/in the BBBlue for librobotcontrol.

I just installed it. So, it will take some time but the servos are working.

I can run the servo and sweep the servo from -1.5 (90 deg cw) to 1.5 (90 deg ccw) by giving the command rc_test_servos -c 1 -p 1.5 but what I am trying to do is to run the servo automatically from +90 to -90 with delay of 5sec by giving pwm. It can run with command rc_test_servos -c 1 -w 1100 for pwm but doesn’t change its position aftewards.
I have pwm in sys/class/pwm/pwmchip0 and I have exported the pwm from it and enabled it and set the duty cycle and period for it but its is not the pwm line or it is not recognizing the chip.
So, I am unable to proceed forward.

Screenshot 2023-04-05 175348

Hello @laasyapriya ,

My C/C++ programming is rusty or never was. Anyway, I will look over the lib. and try to type up a script to test the servo(s) in question. If you want to paste here what you have already included in your source and what errors you are receiving, please do.

I will keep trying.

Seth

P.S. Also:

1. Create a new project: 
  a. Decide on a project name (not new_project_name) and copy the project template (the following is one line): 
     cp -r /usr/share/robotcontrol/rc_project_template ~/new_project_name 
  b. Rename the C source code file: 
     mv rc_project_template.c new_project_name.c 
  c. Edit the Makefile line starting with TARGET to: 
    TARGET = new_project_name 
2. Build the project by calling make from the project folder 
3. Run the project with  ./new_project_name

So, you make the file, add the source, make a remark of the file in the Makefile, then use make to compile.

Then, run the source w/ ./Your_new_File.c or if you have to use sudo, try w/ sudo. I am not sure how your system is set up.

There is a couple of resources online like: Reconsidering the BeagleBone Blue | Servo Magazine and librobotcontrol tutorials - Google Search

Update

So, it seems the PRU controls the servo_header. I think I am in over my head but this will give me some time to learn more. I really know very little about the PRU and its accessibilities.

Another Update

rc_send_esc_pulse_normalized

This may help in your source. I have not found out how to actually use this source just yet. Dang it. This is a far more vast lib. than I remember. It is getting very interesting now to me.

So, if you use rc_send_esc_pulse_normalized, you are basically using your own set of uS onboard the brushless ESC which controls the motors from the Servo Headers (I think).

If you do not want to do this triggering of your own uS, try the regular:

  1. Turn off the power rail
  2. Turn on the power rail (Servo Header)
  3. Then, enable your pins 1 - 8

But beware, do not use PWR w/ a brushless ESC on the Servo Header. This way, you can use both.

Both of the servos and ESC can be used to handle the motion at the same time.

For some reason, there is also a doc. on BEC use. I have not used a BEC before today. So, I may not mess w/ this idea of BEC usage. DO NOT use a BEC and enable the 6v regulator onboard which controls the PWR section to the Servos.

A BEC enabled brushless ESC will cause damage to some component, i.e. ESC or even worse another onboard component.

RC_ESC_DEFAULT_MIN_US (1000) to RC_ESC_DEFAULT_MAX_US (2000)

That is it for now. I mean, those are the defaults. I am trying some source so far. I HAVE NOT TESTED IT YET!

I still am working on it but it seems that the Strawson fellow and whomever else that wrote the lib. has functions for this type of stuff and then there is pure C/C++:

#include <rc/servo.h>
#include <rc/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <rc/adc.h>
// #include <rc/dsm.h>
#include <signal.h>
#include <getopt.h>

static int running;

typedef enum test_mode_t {
  DISABLED,
  MICROSECONDS,
  SWEEP
} test_mode_t;

// CNTRL-C stuff
static void __signal_handler(__attribute__ ((unused)) int dummy) {
  running = 0;
  return;
}

int main(int argc char *argv[]) {
  double servo_pos = 0;
  double sweep_limit = 0;
  int width_us = 0;
  int ch = 0;
  double direction = 1;
  test_mode_t mode = DISABLED;
  int frequency_hz = 50;
  int i, c;
  
  // Some atoi scheduling
  opterr = 0;
  while ((c = getopt(argc, argv, "c:s")) != -1) {
    switch (c) {
	case 'c':
	  ch = atoi(optarg);
	  if(ch < RC_SERVO_CH_MIN || ch > RC_SERVO_CH_MAX) {
	    fprintf(stderr, "Error, must be in b/t %d and %d\n", RC_SERVO_CH_MIN, RC_SERVO_CH_MAX);
		return -1;
	  }	
	// SWEEP
    case: 's':
	  // Use only one mode!
	  if(mode!=DISABLED) {
	    __print_usage();
		return - 1;
	  }
	  sweep_limit = atof(optarg);
	  if(sweep_limit > 1.5 || sweep_limit < -1.5) {
	    fprintf(stderr, "Error, please sweep from -1.5 to 1.5\n");
		return -1;
	  }
      mode = SWEEP;
	  servo_pos = 0.0;
	  break;
    }	
    if(mode==DISABLED) {
      fprintf(stderr, "There was not enough input on args\n");
	  __print_usage();
	  return -1;
    }
  
    signal(SIGINT, __signal_handler);
    running = 1;
  
    // Connect the Battery
    if(rc_adc_init()) {
      fprintf(stderr, "Error, please connect the battery!");
      return -1;
    }	
    rc_adc_batt() < 6.0) {
      fprintf(stderr, "Disconnected battery or low levels of charge...\n");
	  return - 1;
    }
    rc_adc_cleanup();
  
    // PRU Stuff (I Think)...
    if(rc_servo_init()) return -1; // This is how it seems...
  
    // On goes the PWR
    rc_servo_power_rail_en(1);
  
    if(ch==0) printf("ALL CHANNELS of the SERVO HEADER...\n);
    else printf(Sending to %d channels...\n", ch, ch, ch);
    switch(mode) {
    case SWEEP:
      printf("You are sweeping!", sweep_limit);
	  break;
    default:
      // This means we are in trouble?
	  fprintf(stderr, "Error, Invalid modes\n");
	  return -1;
    }
  
    // Main Loop at 50 Hz?
    while(running) {
      switch(mode) {
	
	  case SWEEP:
	    // increase and descrease?
	    servo_pos += direction * sweep_limit / frequency_hz;
	  
	    // reset and start from scratch
	    if(servo_pos > sweep_limit) {
	      servo_pos = sweep_limit;
		  direction = -1.0;
	    }
	    else if(servo_pos < (-sweep_limit)) {
	      servo_pos = -sweep_limit;
		  direction = 1;
	    }
	    // The results are in...
	  }
	  break;
	
    default:
      fprintf(stderr, "ERROR unhandled mode...\n");
	  return -1;
    }
	
	// sleeping or trying to!
	rc_usleep(50000 / frequency_hz);
	break;
  }
  
  rc_usleep(10000);
  // Turn it off for now!
  rc_servo_power_rail_en(0);
  rc_servo_cleanup();
  return 0;
}

I got most of it from the lib. I need to test it. If you are daring, you can try but it is HIGHLY UNTESTED and I would not do it if I were you. Take your propellers off if you have an ESC w/out BEC and some SERVOS.

Seth

P.S. It is getting late now. I may not test until Thu. or Fri. in US time. So, that errors out since it is the lib. in a file to be used as a template. Okay, another day and another time. I will keep on it. I got what you want.

You want to have source for sweeping motions w/ your source but w/ a substitution of movement but w/ time instead of movement. Okay…just give me some time.

Thank you for your insight and the guidance you provided it was really helpful and thank you for your consideration and look forward to hearing from you.

import time
import signal
import sys

pwmPeriod = ‘20000000’ # Period in ns, (20 ms)
pwm = ‘1’ # pwm to use
channel = ‘b’ # channel to use
PWMPATH=‘/dev/bone/pwm/’+pwm+‘/’+channel
low = 0.8 # Smallest angle (in ms)
hi = 2.4 # Largest angle (in ms)
ms = 250 # How often to change position, in ms
pos = 1.5 # Current position, about middle ms)
step = 0.1 # Step size to next position

def signal_handler(sig, frame):
print(‘Got SIGINT, turning motor off’)
f = open(PWMPATH+‘/enable’, ‘w’)
f.write(‘0’)
f.close()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print(‘Hit ^C to stop’)

f = open(PWMPATH+‘/period’, ‘w’)
f.write(pwmPeriod)
f.close()
f = open(PWMPATH+‘/enable’, ‘w’)
f.write(‘1’)
f.close()

f = open(PWMPATH+‘/duty_cycle’, ‘w’)
while True:
pos += step # Take a step
if(pos > hi or pos < low):
step = -1
duty_cycle = str(round(pos
1000000)) # Convert ms to ns
# print('pos = ’ + str(pos) + ’ duty_cycle = ’ + duty_cycle)
f.seek(0)
f.write(duty_cycle)
time.sleep(ms/1000)

This is a example code for beaglebone black in python which you shared me before. I have configured the PWM and enabled it set the duty cycle and period similar to the code but in C and I have changed the duty cycle and gave some delay and running the program. It is not showing me any error but servo connected to the BBBlue is not moving.

1 Like

Hello,

Okay. First off, the lib. does not provide perse PWM handling the Servo Header on the BBBlue. The PRU provides this mechanism via source to handle PWM on the Servo Header.

I think I was not clear enough.

Also, writing to FDs for /sys/class/pwm/ will most likely fail w/ this librobotcontrol lib. b/c of the fact that the PRU handles this subsystem for you or anyone else using this lib.

Phew and okay, I will keep trying. This lib. always interested me and I wanted to learn more but never had time.

Seth

P.S. You will need to use the PRUSS and that entails using the already configured PRUSS PWM usage on the BBBlue w/ librobotcontrol.

Now, the source may be a bit different but it allows for more am335x usage b/c of it offloading the the PRUSS. Off to keep trying! So, something like but different, i.e. as I have not perfected the art of source mfg. yet.

// Trying Out Some Source from LibRobotControl
// For debugging and testing w/ laasyapriya
// W/ some testing from Seth and some source from librobotcontrol theory...

#include <robotcontrol.h>
#include <stdio.h>

#define RC_SERVO_CH_MIN 1
#define RC_SERVO_CH_MAX 8
#define RC_ESC_DEFAULT_MIN_US 1000
#define RC_ESC_DEFAULT_MAX_US 2000


int main() {
	int min_us = RC_ESC_DEFAULT_MIN_US;
	int max_us = RC_ESC_DEFAULT_MAX_US;
	int servo_pos 0.0;
	double sweep_limit 1.0;
	int ch 1;
	double direction 1;
	int frequency_hz 50;
	int i, val;
} 
	// Main Loop at 50 Hz?
	while(1) {		
	    // increase and descrease?
		servo_pos += direction * sweep_limit / frequency_hz;
	  
		// reset and start from scratch
		if(servo_pos > sweep_limit) {
			servo_pos = sweep_limit;
			direction = -1.0;
		}
		else if(servo_pos < (-sweep_limit)) {
			servo_pos = -sweep_limit;
			direction = 1;
		// The results are in...
		}
	}

	// sleeping or trying to!
	rc_usleep(50000 / frequency_hz);
	break;

int rc_servo_init(void) {
	// Start and Configure the PRU for sending Servo Pulses...
}

int rc_servo_power_rail_en(1) {
}

int rc_servo_set_esc_range(min_us, max_us) {
}

int rc_servo_send_pulse_us(1, 50) {
	for(i = 1; i <= 8; i++) {
		val = ch;
		if(val > 0) {
			rc_servo_send_pulse_us(i, val);
		}
	}
}

I will test this source and return service. Enjoy!

Okay, I am receiving some negative output so far but we can debug if necessary:

mark_one.c:15:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before numeric constant
   15 | int servo_pos 1;
      |               ^
mark_one.c:16:20: error: expected '=', ',', ';', 'asm' or '__attribute__' before numeric constant
   16 | double sweep_limit 1.0;
      |                    ^~~
mark_one.c:17:8: error: expected '=', ',', ';', 'asm' or '__attribute__' before numeric constant
   17 | int ch 1;
      |        ^
mark_one.c:18:18: error: expected '=', ',', ';', 'asm' or '__attribute__' before numeric constant
   18 | double direction 1;
      |                  ^
mark_one.c:19:18: error: expected '=', ',', ';', 'asm' or '__attribute__' before numeric constant
   19 | int frequency_hz 50;
      |                  ^~
mark_one.c:26:28: error: expected declaration specifiers or '...' before numeric constant
   26 | int rc_servo_power_rail_en(1) {
      |                            ^
mark_one.c:32:28: error: expected declaration specifiers or '...' before numeric constant
   32 | int rc_servo_send_pulse_us(1, 50) {
      |                            ^
mark_one.c:32:31: error: expected declaration specifiers or '...' before numeric constant
   32 | int rc_servo_send_pulse_us(1, 50) {
      |                               ^~
mark_one.c: In function 'main':
mark_one.c:45:3: error: 'servo_pos' undeclared (first use in this function)
   45 |   servo_pos += direction * sweep_limit / frequency_hz;
      |   ^~~~~~~~~
mark_one.c:45:3: note: each undeclared identifier is reported only once for each function it appears in
mark_one.c:45:16: error: 'direction' undeclared (first use in this function)
   45 |   servo_pos += direction * sweep_limit / frequency_hz;
      |                ^~~~~~~~~
mark_one.c:45:28: error: 'sweep_limit' undeclared (first use in this function)
   45 |   servo_pos += direction * sweep_limit / frequency_hz;
      |                            ^~~~~~~~~~~
mark_one.c:45:42: error: 'frequency_hz' undeclared (first use in this function)
   45 |   servo_pos += direction * sweep_limit / frequency_hz;
      |                                          ^~~~~~~~~~~~
mark_one.c:61:2: error: break statement not within loop or switch
   61 |  break;
      |  ^~~~~
/usr/include/rc/servo.h: In function 'rc_servo_init':
mark_one.c:24:1: warning: control reaches end of non-void function [-Wreturn-type]
   24 | }
      | ^
/usr/include/rc/servo.h: In function 'rc_servo_set_esc_range':
mark_one.c:30:1: warning: control reaches end of non-void function [-Wreturn-type]
   30 | }
      | ^
make: *** [Makefile:36: mark_one.o] Error 1

That is from make clean && make in the librobotcontrol/rc_project_template/ directory for my file I am trying to manage.

Hello,

I see that kernel 4.14.x was the last known kernel to work w/ this lib.

Have you made any progress? I will try off and on intermittently and keep trying to port the build to kernel 5.10.x.

I think it should just work but a lot has changed in DTS and w/ how beagleboard.org calls for pinctrl and so on in DTS.

Seth

P.S. Just to reiterate, you may need the older .dtb in the /boot/uEnv.txt file to handle the changed updates in DTS.

Again, this is untested and may break your system. Always back up the info. and data you would like to keep when attempting changes.

dtb=am335x-boneblue.dtb

But, you may need to find out what was then, what is now, and what has changed in the DTS files. It is a lot to take on w/ all of what is going on right now. I will keep trying at times but I cannot promise anything.

Thank you for your input I really appreciate it and I will go through the dtb files and check on it and thank you for trying it’s okay if it doesn’t work I will try another way.

Hello @laasyapriya ,

I think when kernel 4.14.x or even maybe kernel 4.19.x was around, using the am335x-boneblue.dtb in /boot/uEnv.txt was necessary. I am not completely sure.

I have been testing w/ kernel 5.10.x lately.

Seth

P.S. If I can configure something w/ the C/C++ source, I will update you. I must have the main function before the required item functions. The compilation in C/C++ worked but the source does nothing. I am still trying here…

// Trying Out Some Source from LibRobotControl
// For debugging and testing w/ laasyapriya
// W/ some testing from Seth and some source from librobotcontrol theory...

#include <robotcontrol.h>
#include <stdio.h>
#include <stdlib.h>

#define RC_SERVO_CH_MIN 1
#define RC_SERVO_CH_MAX 8
#define RC_ESC_DEFAULT_MIN_US 1000
#define RC_ESC_DEFAULT_MAX_US 2000

int min_us = RC_ESC_DEFAULT_MIN_US;
int max_us = RC_ESC_DEFAULT_MAX_US;
int servo_pos = 0;
double sweep_limit = 0;
int ch = 1;
double direction = 1;
int frequency_hz = 50;
int i, val;
int us = 500000;

int main() {
        // Main Loop at 50 Hz?
        while(1) {
            // increase and descrease?
                servo_pos += direction * sweep_limit / frequency_hz;

                // reset and start from scratch
                if(servo_pos > sweep_limit) {
                        servo_pos = sweep_limit;
                        direction = -1.0;
                }
                else if(servo_pos < (-sweep_limit)) {
                        servo_pos = -sweep_limit;
                        direction = 1;
                // The results are in...
                }
        }

        // sleeping or trying to!
        rc_usleep(500000 / frequency_hz);
}

int rc_servo_init(void) {
        // Start and Configure the PRU for sending Servo Pulses...
        return 0;
}
int rc_servo_power_rail_en(en) {
        return 0;
}

int rc_servo_set_esc_range(min_us, max_us) {
        return 0;
}

int rc_servo_send_pulse_us(int ch, int us) {
        for(i = 1; i <= 8; i++) {
                val = ch;
                if(val > 0) {
                        rc_servo_send_pulse_us(i, val);
                        return 0;
                }
        }
}

I think it is the last } mark before what was supposed to be the main function. Anyway, on w/ testing!

Update

Now, w/out error but still this source does not do anything!

// Trying Out Some Source from LibRobotControl
// For debugging and testing w/ laasyapriya
// W/ some testing from Seth and some source from librobotcontrol theory...

#include <robotcontrol.h>
#include <stdio.h>
#include <stdlib.h>

#define RC_SERVO_CH_MIN 1
#define RC_SERVO_CH_MAX 8
#define RC_ESC_DEFAULT_MIN_US 1000
#define RC_ESC_DEFAULT_MAX_US 2000

int min_us = RC_ESC_DEFAULT_MIN_US;
int max_us = RC_ESC_DEFAULT_MAX_US;
double servo_pos = 0;
double sweep_limit = 0;
int ch = 1;
double direction = 1;
int frequency_hz = 50;
int i, val;

int main() {
        // Main Loop at 50 Hz?
        while(ch == 1) {
            // increase and descrease?
                servo_pos += direction * sweep_limit / frequency_hz;

                // reset and start from scratch
                if(servo_pos > sweep_limit) {
                        servo_pos = sweep_limit;
                        direction = -1.0;
                }
                else if(servo_pos < (-sweep_limit)) {
                        servo_pos = -sweep_limit;
                        direction = 1;
                // The results are in...
                }
        }

        // sleeping or trying to!
        rc_usleep(1000000 / frequency_hz);
        return 0;
}

int rc_servo_init(void) {
        // Start and Configure the PRU for sending Servo Pulses...
        return 0;
}
int rc_servo_power_rail_en(en) {
        return 0;
}

int rc_servo_set_esc_range(min_us, max_us) {
        return 0;
}

int rc_servo_send_pulse_normalized(int ch, double servo_pos) {
        for(servo_pos = 1; servo_pos <= 8; servo_pos++) {
                val = ch;
                if(val > 0) {
                        rc_servo_send_pulse_normalized(i, val);
                        servo_pos = 1;
                        rc_usleep(100000);
                        servo_pos = -1;
                        rc_usleep(100000);
                }
        }
        return 0;
}

If you can see why the source does nothing or understand the reasoning, awesome. If not, I will keep on trying. Good luck…

Thank you for your hard work. I will see what is the issue in the source and if I find it I will let you know. Thank you so much once again.

If rc_test_servos works correctly then you should not be messing with dtbs, the only thing you could accomplish by doing so is turn a working setup into a broken one.

The servo outputs on the BeagleBone Blue are not PWM outputs in the traditional sense and are not controlled via /sys/class/pwm, they’re controlled via the servo API of librobotcontrol.

I’m not particularly familiar with librobotcontrol myself, but the rc_test_servos -c 1 -w 1100 command appears to be equivalent to rc_servo_send_pulse_us( 1, 1100 )

The code snippets from silver2row are all nonsensical, either syntactically or because they’re redefining functions that are provided by librobotcontrol (which will therefore either result in a link error or at the very least completely break the library).

1 Like

@zmatt ,

Thank you. I am starting w/ this lib. just recently. rc_servo_send_pulse_us(1, 1100). Okay.

I will try again.

@laasyapriya , just a heads up. I am lacking in librobotcontrol source understandings. So, I may not be the best person to use for this error.

But… @zmatt is right. The PRU handles the PWM instances I think.

Seth

P.S. I will keep on trying.

thank you for working on my problem. I am trying to configure the GPIOchip as pwm line to give power to the servo.

1 Like

Hello @laasyapriya ,

I found some more resources for you: beaglebone-blue/BeagleBone_Blue_Pin_Table.csv at master · beagleboard/beaglebone-blue · GitHub .

If you plan on using Librobotcontrol, okay. If not, I may be able to think of someway to handle the GPIO to enable the Servo Headers but I cannot be sure…

I mostly tried to use the BBBlue for arducopter years and years ago.

Seth

P.S. I think pathlib in python3 or gpiod may help you w/ enabling the Servo Headers. Now, about the PWM channels on the Servo Headers, I am not quite sure…

Are the headers controlled via GPIO or PWM?