Controlling servos using JeVois and Arduino
Serial strings output by JeVois modules
In this simple example, we create an Arduino program that will listen for messages from DemoSaliency, RoadNavigation, ObjectTracker, DemoArUco, or other modules that output messages over serial port that contain information about the location of a target. These modules output strings of the form:
T1 <target_x>
for one-dimentional guidance (e.g., direction of the vanishing point in RoadNavigation), or
T2 <target_x> <target_y>
for two-dimensional coordinates. See Standardized serial messages formatting for information about customizing thee serial messages.
To make the outputs independent of video image resolution, coordinates are always normalized by all modules ot a range of -1000 (full left or full up) to 1000 (full right or full down).
One string is typically output on every video frame, that is, these strings are coming out of the JeVois camera at rates of 30 per second, 60 per second, or more.
Arduino servo control
Here is a simple piece of Arduino code that can parse the strings sent by JeVois and convert them into pulses that will control the angle of servo-motors. This code can be used to control the steering of a radio-controlled car, or to control the pan and tilt angles of a servo-based electric pan/titl head onto which the JeVois camera is mounted.
#include <Servo.h>
#define LEDPIN 13
#define SERIAL Serial1
Servo panservo;
#define PANPIN 3
Servo tiltservo;
#define TILTPIN 5
#define PANZERO 90
#define TILTZERO 90
#define SCALE 100
long pangain = 100;
long tiltgain = 100;
long panval = PANZERO * SCALE;
long tiltval = TILTZERO * SCALE;
#define INLEN 128
char instr[INLEN + 1];
void setup()
{
SERIAL.begin(115200);
SERIAL.setTimeout(1000000);
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN, LOW);
panservo.attach(PANPIN);
panservo.write(panval / SCALE);
tiltservo.attach(TILTPIN);
tiltservo.write(tiltval / SCALE);
SERIAL.println("setpar serlog None");
SERIAL.println("setpar serout Hard");
}
void loop()
{
digitalWrite(LEDPIN, LOW);
byte len = SERIAL.readBytesUntil('\n', instr, INLEN);
instr[len] = 0;
digitalWrite(LEDPIN, HIGH);
char * tok = strtok(instr, " \r\n");
int state = 0; int targx = 0, targy = 0;
while (tok)
{
switch (state)
{
case 0:
if (strcmp(tok, "T2") == 0) state = 1;
else if (strcmp(tok, "T1") == 0) state = 4;
else if (strcmp(tok, "PANGAIN") == 0) state = 6;
else if (strcmp(tok, "TILTGAIN") == 0) state = 8;
else state = 1000;
break;
case 1: targx = atoi(tok); state = 2; break;
case 2: targy = atoi(tok); state = 3; break;
case 4: targx = atoi(tok); state = 5; break;
case 6: pangain = atoi(tok); state = 7; break;
case 8: tiltgain = atoi(tok); state = 9; break;
default: break;
}
tok = strtok(0, " \r\n");
}
if (state == 3 || state == 5)
{
panval -= (targx * pangain) / 1000;
if (panval < 5 * SCALE) panval = 5 * SCALE; else if (panval > 175 * SCALE) panval = 175 * SCALE;
panservo.write(panval / SCALE);
}
if (state == 3)
{
tiltval += (targy * tiltgain) / 1000;
if (tiltval < 5 * SCALE) tiltval = 5 * SCALE; else if (tiltval > 175 * SCALE) tiltval = 175 * SCALE;
tiltservo.write(tiltval / SCALE);
}
}
Using a script.cfg file on the JeVois platform
Sometimes, it is useful to set some parameters or execute some commands when a module is loaded.
JeVois allows you to store parameter settings and commands in a file named script.cfg
stored in the directory of a module. The file script.cfg
may contain any sequence of commands as you would type them interactively in the JeVois command-line interface.
Here is an example for the ObjectTracker module. As you can see below, the commands here will not only set parameters on JeVois, but will also set the pan and tilt gains of the Arduino-controlled pan/tilt head:
setcam autowb 0
setcam autogain 0
setcam autoexp 0
setcam redbal 110
setcam bluebal 170
setcam gain 16
setcam absexp 500
setpar hrange 95...110
setpar srange 100...255
setpar vrange 60...253
setpar serlog None
setpar serout Hard
serout PANGAIN 400
serout TILTGAIN 300