I am back on track, in a cautious manner. I put the li-ion battery pack back in, but I turned the servos around, now I have the wires away from the battery pack, which allows me to jiggle the bad wiring connection on the servo that is acting up. I will have to see how this new configuration affects the maneuverability of the robot. I ordered a couple of new servos, so next week I will have that problem resolved, but it will be in the new configuration.
I also re-installed the Wheel Encoder kit, have it wired up and I am ready to start capturing some data, once I figure out the correct code. Below is the sample code for the Stamp, the big problem is
New(Side) = INS.LOWBIT(Sense + Side) 'Read new encoder value.
, what is the C version of this? I do not recall seeing any thing in C that allows you to read LOW BIT or HIGH BIT, so I am not sure as to how to manipulate the byte value in that manner.
I also ordered the Parallax compass, now I have to start thinking about what to do about the data that will be available from the encoder and compass. I also will be adding the softRTC program, so I could have time, distance, and direction values for a navigation algorithm.
Ray
DigitalEncoderDoc
'{$STAMP BS2}
'{$PBASIC 2.5}
'Program to traverse a 5-pointed star. Straight sections are about 25" long.
'Angle of each turn is 144-degrees. Use it to test the encoders. If the left one
'fails to function, the Boe-Bot will just continue going in a straight line
'without stopping. If the right one fails, it will continue to circle in the turn.
'Ideally, it will come to rest at the point and direction in which it started.
'But it's uncalibrated, so that's somewhat unlikely!
'---------[Constants]----------------------------------------------------------
RIGHT CON 0 'Constants defining direction subscripts.
LEFT CON 1
SenseR PIN 10 'Righthand encoder input.
SenseL PIN 11 'Lefthand encoder input. (MUST be SenseR + 1.)
MotorR PIN 12 'Righthand motor output.
MotorL PIN 13 'Lefthand motor output. (MUST be MotorR + 1.)
Sense CON SenseR 'Base address for encoders.
Motor CON MotorR 'Base address for motors.
'---------[Variables]----------------------------------------------------------
Prev VAR Bit(2) 'Previous readings from encoders.
New VAR Bit(2) 'Current readings from encoders.
Side VAR Bit 'Side index (LEFT or RIGHT).
Counter VAR Word(2) 'Pulse counters for encoders.
i VAR Byte 'FOR/NEXT index
'---------[Program begins here.]-----------------------------------------------
PAUSE 3000 'Time to remove finger from reset button...
FOR i = 1 TO 5
Counter(LEFT) = 0 'Initialize LEFT counter.
DO WHILE (Counter(LEFT) < 50)
PULSOUT MotorL, 850 'Pulse the servos to go straight
PULSOUT MotorR, 650 'by 50 pulse edges (about 25").
GOSUB Update 'Update the encoder counts.
PAUSE 20 '20 ms pulse gap.
LOOP
PAUSE 500 'Wait 1/2 second before turn.
Counter(RIGHT) = 0 'Initialize RIGHT counter.
DO WHILE (Counter(RIGHT) < 20)
PULSOUT MotorR, 650 'Pulse the RIGHT servo to turn a 40% circle.
GOSUB Update 'Update the encoder counts.
PAUSE 20 '20 ms pulse gap.
LOOP
PAUSE 500 'Wait 1/2 second before next side.
NEXT
END
'---------[Subroutines]--------------------------------------------------------
Update: 'Update pulse counts from the encoders.
'Just call it often enough to catch all the
'changes.
FOR Side = RIGHT TO LEFT 'For both encoders...
New(Side) = INS.LOWBIT(Sense + Side) 'Read new encoder value.
IF (New(Side) ^ Prev(Side)) THEN 'Different from last value?
Prev(Side) = New(Side) ' Yes: Update with new value.
Counter(Side) = Counter(Side) + 1 ' Update counter.
ENDIF
NEXT
RETURN
Below is my version of trying to read the Wheel Encoder Data. I just wanted to see if I could read anything on the encoder pin, I am just using the left servo for this exercise. I added the 'e' command to view the encoder data for that key press, and then compare it to the next couple of key presses. The only number that I am getting is 2048, not sure what that number represents, if anything. What I was expecting to see is a different number on each keypress, that would mean that the encoder was reacting to the servo movement. Because the encoder is an IR contraption, I was, at first, expecting to see 0 or 1, as the data. The 2048 number appears when I have LeftEncoderData = datamask, now when I use LeftEncoderData = INA + datamask, I get a negative six digit number, but the same number. When I added the INA, I really was expecting to see 0 or 1, because the INA is supposed to be reading whether the pin is (0)ground or (1)VDD. Now I am not sure what the next step should be.
Ray
/**
* @file RemBotBase.c
* This is the main RemBotBase program start point.
* This is a basic testing program. It has
* 's' stop, 'f' forward, 'b' backward,
* '+' increase speed, '-' decrease speed.
*/
#include <propeller.h>
#include <stdio.h>
#include <sys/thread.h>
#define STACK_SIZE 32
int LEFT_SERVO_PIN = 19;
int RIGHT_SERVO_PIN = 18;
int LEFT_ENCODER_PIN = 11;
int RIGHT_ENCODER_PIN = 10;
#define LEFT_CENTER 1500
#define RIGHT_CENTER 1500
#define PAUSE_DIVISOR 50
/* stacks for COGs */
static int LeftServoStack [STACK_SIZE];
static int RightServoStack [STACK_SIZE];
/* per-thread library variables */
static _thread_state_t LeftThreadData;
static _thread_state_t RightThreadData;
/* WheelServo COG variables */
int LeftServoSpeed;
int RightServoSpeed;
int LeftRotation;
int RightRotation;
int StopNoPulse = 0; //1
static int MaxServoSpeed = 500;
int LeftEncoderData;
int RightEncoderData;
void LeftServoThread(void *arg __attribute__((unused)))
{
int pinmask = (1<<LEFT_SERVO_PIN);
int center = LEFT_CENTER;
int ustime = CLKFREQ/1000000;
int datamask = (1<<LEFT_ENCODER_PIN);
DIRA |= pinmask;
for(;;) {
/* start with signal off */
OUTA &= ~pinmask;
if(StopNoPulse && LeftServoSpeed == 0) {
waitcnt(CLKFREQ/PAUSE_DIVISOR+CNT);
LeftRotation = 0;
continue;
}
if(LeftServoSpeed > MaxServoSpeed)
LeftServoSpeed = MaxServoSpeed;
if(LeftServoSpeed < -MaxServoSpeed)
LeftServoSpeed = -MaxServoSpeed;
/* move servo */
LeftRotation = (LeftServoSpeed/2*center)/MaxServoSpeed+center;
waitcnt(CLKFREQ/PAUSE_DIVISOR+CNT);
OUTA |= pinmask;
waitcnt(ustime*LeftRotation+CNT);
OUTA ^= pinmask;
//LeftEncoderData = (INA + datamask);
LeftEncoderData = datamask;
}
}
void RightServoThread(void *arg __attribute__((unused)))
{
int pinmask = (1<<RIGHT_SERVO_PIN);
int center = RIGHT_CENTER;
int ustime = CLKFREQ/1000000;
DIRA |= pinmask;
for(;;) {
/* start with signal off */
OUTA &= ~pinmask;
if(StopNoPulse && RightServoSpeed == 0) {
waitcnt(CLKFREQ/PAUSE_DIVISOR+CNT);
RightRotation = 0;
continue;
}
if(RightServoSpeed > MaxServoSpeed)
RightServoSpeed = MaxServoSpeed;
if(RightServoSpeed < -MaxServoSpeed)
RightServoSpeed = -MaxServoSpeed;
/* move servo */
RightRotation = (-RightServoSpeed/2*center)/MaxServoSpeed+center;
waitcnt(CLKFREQ/PAUSE_DIVISOR+CNT);
OUTA |= pinmask;
waitcnt(ustime*RightRotation+CNT);
OUTA ^= pinmask;
}
}
void startServoThreads(void)
{
int n;
n = _start_cog_thread(LeftServoStack + STACK_SIZE, LeftServoThread, NULL, &LeftThreadData);
n = _start_cog_thread(RightServoStack + STACK_SIZE, RightServoThread, NULL, &RightThreadData);
}
void botStop(void)
{
LeftServoSpeed = 0;
RightServoSpeed = 0;
}
void botForward(int rate)
{
LeftServoSpeed = rate;
RightServoSpeed = rate;
}
void botReverse(int rate)
{
LeftServoSpeed = -rate;
RightServoSpeed = -rate;
}
void botSpeed(int rate)
{
LeftServoSpeed = LeftServoSpeed >= 0 ? rate : -rate;
RightServoSpeed = RightServoSpeed >= 0 ? rate : -rate;
}
/**
* Main program function.
*/
int main(void)
{
int speed = 20;
char cmdstr[2];
int cmd;
setvbuf(stdin, NULL, _IONBF, 0); // no buffering stdin
setvbuf(stdout, NULL, _IONBF, 0); // no buffering stdout
stdin->_flag |= _IOCOOKED; // turn on echo
waitcnt(CLKFREQ + CNT);
startServoThreads();
printf("Threads started\n");
for(;;) {
putchar('>');
fgets(cmdstr, 2, stdin);
cmd = cmdstr[0];
if(!cmd) {
continue;
}
switch(cmd) {
case 's':
botStop();
printf("\n");
break;
case 'f':
botForward(speed);
printf("Forward %d\n",speed);
break;
case 'b':
botReverse(speed);
printf("Backward %d\n",speed);
break;
case '-':
if(speed >= 10) speed -= 10;
printf("speed- %d\n",speed);
botSpeed(speed);
break;
case '+':
if(speed <= 90) speed += 10;
printf("speed+ %d\n",speed);
botSpeed(speed);
break;
case 'e':
printf("left %d\n",LeftEncoderData);
break;
}
}
return 0;
}
After trying to find out what that decimal 2048 number is, in binary it is, 100000000000, means that pin 11 is high. So that means that there could be some electrical action on the pin, but how do I read the information that the pin is supposedly providing? I do not think that the encoder assembly is sending serial? If it is some other method of providing data, in C what other ways is there to read data from a pin? I have not run across any C commands like encoderData = input(pin11), or maybe there is something like that in the PropGCC library. I guess I need some help on this one.
Thanks for the link jazzed, I tried the program, and all I get is a zero for the response to the encoders. I used the wiring diagram that is shown in the encoder docs, and I also double checked the connections, and still get a zero as the output for the encoders, so not sure what the next step is.
I also got my new servos installed, and they seem to be working as expected. I will do some micro surgery on the old servo to see if I can fix the loose wiring connector, that should be an interesting experience.
I also received the compass, luckily there is some spin code for using that, but the PropBOE does not have access to the SDA, and SDL, so you have to use some new pins in order to use the compass, what a waste of limited amount of pins that are available.
For another possible project, I received a Propeller Servo Controller USB (PSCU), since the firmware that is available is in Spin code, it might be an interesting coding project to write some C code for it. Something that would challenging with this is, how do you provide control of sixteen servo connections within one cog? Or how else would you do it?
I just took the back plate off of the servo, the soldered connections on the pcb are fine, the problem is the wires were crimped and hidden within the grommet. I am not going to send this back to Parallax, I will cut the wires at the crimp, and solder that back to the pcb, as soon as I acquire a very fine tip for my soldering iron. I figure it is a one in a million screw up, so I will just fix it. So, if your servos are misbehaving there is the possibility that you might have some crimped wires hidden within the grommet. Probably some worker or machine misused the grommet insertion tool.
Thanks for the link jazzed, I tried the program, and all I get is a zero for the response to the encoders. I used the wiring diagram that is shown in the encoder docs, and I also double checked the connections, and still get a zero as the output for the encoders, so not sure what the next step is.
I looked for an encoder kit at my local radio shack ... no luck.
I also received the compass, luckily there is some spin code for using that, but the PropBOE does not have access to the SDA, and SDL, so you have to use some new pins in order to use the compass, what a waste of limited amount of pins that are available.
Yes, I noticed the lack of easy access to the I2C pins also. PITA for probing also.
David did work on some demo code for a compass. It is in the propeller-gcc demos propboe folder.
For another possible project, I received a Propeller Servo Controller USB (PSCU), since the firmware that is available is in Spin code, it might be an interesting coding project to write some C code for it. Something that would challenging with this is, how do you provide control of sixteen servo connections within one cog? Or how else would you do it?
Beau's servo PASM does that. It should be easy to leverage it. Porting it to COGC would be an advanced topic
I am using a continue servo, and with your code I can only seem to run the servo at one speed regardless of the input and at counter clockwise. Would you have any idea how I could reverse the servo? I have tried putting a negative value, but it does not seem to change anything.
I am using a continue servo, and with your code I can only seem to run the servo at one speed regardless of the input and at counter clockwise. Would you have any idea how I could reverse the servo? I have tried putting a negative value, but it does not seem to change anything.
Hi.
Welcome to the forum.
Do you have the servos properly connected? What pins are you using?
Do you have a battery pack on your BOT? Just using the USB power won't work.
I remember pointing folks interested in XBee to the PropBoeXBee code. The program is "menu driven" and the pins must be connected from XBee D0 to Propeller P0 and XBee D1 to Propeller P1. To control the bot, the XBee terminal must be set to 9600Baud and the XBee controller connected to USB on your computer.
The PropBoeXBee program commands are:
'-': decrease speed.
'+': increase speed.
'C': calibrate. adjust servos so they don't move.
'f': move forward.
'b': move backwards.
'l': turn left.
'r': turn right.
'L': spin left (both wheels turn).
'R': spin right (both wheels turn).
's': stop.
The bot won't move until you tell it to move with one of the commands.
Use C to calibrate the servos when you get them moving.
Comments
I also re-installed the Wheel Encoder kit, have it wired up and I am ready to start capturing some data, once I figure out the correct code. Below is the sample code for the Stamp, the big problem is , what is the C version of this? I do not recall seeing any thing in C that allows you to read LOW BIT or HIGH BIT, so I am not sure as to how to manipulate the byte value in that manner.
I also ordered the Parallax compass, now I have to start thinking about what to do about the data that will be available from the encoder and compass. I also will be adding the softRTC program, so I could have time, distance, and direction values for a navigation algorithm.
Ray
Ray
Ray
I don't have an encoder, so i can't do any testing. If you have code questions, I'll try to answer them.
I also got my new servos installed, and they seem to be working as expected. I will do some micro surgery on the old servo to see if I can fix the loose wiring connector, that should be an interesting experience.
I also received the compass, luckily there is some spin code for using that, but the PropBOE does not have access to the SDA, and SDL, so you have to use some new pins in order to use the compass, what a waste of limited amount of pins that are available.
For another possible project, I received a Propeller Servo Controller USB (PSCU), since the firmware that is available is in Spin code, it might be an interesting coding project to write some C code for it. Something that would challenging with this is, how do you provide control of sixteen servo connections within one cog? Or how else would you do it?
Ray
Ray
I looked for an encoder kit at my local radio shack ... no luck.
Good to know. Thanks.
Yes, I noticed the lack of easy access to the I2C pins also. PITA for probing also.
David did work on some demo code for a compass. It is in the propeller-gcc demos propboe folder.
Beau's servo PASM does that. It should be easy to leverage it. Porting it to COGC would be an advanced topic
I am using a continue servo, and with your code I can only seem to run the servo at one speed regardless of the input and at counter clockwise. Would you have any idea how I could reverse the servo? I have tried putting a negative value, but it does not seem to change anything.
Hi.
Welcome to the forum.
Do you have the servos properly connected? What pins are you using?
Do you have a battery pack on your BOT? Just using the USB power won't work.
I remember pointing folks interested in XBee to the PropBoeXBee code. The program is "menu driven" and the pins must be connected from XBee D0 to Propeller P0 and XBee D1 to Propeller P1. To control the bot, the XBee terminal must be set to 9600Baud and the XBee controller connected to USB on your computer.
The PropBoeXBee program commands are:
Use C to calibrate the servos when you get them moving.
Hope this helps.