I have a robot that I am controlling and it receives the first command but then refuses to receive any commands there after. I’m controlling the robot with the arrows via javascript JQUERY DOM. It’s almost like the code isn’t receiving the onclick changes or the core isn’t getting the new messages.
I hard coded speeds for all functions but the forward one, just to test.
Servo left; // create servo object to control a servo
Servo right;
#define PIN D7
int leftpin = A0;
int rightpin = A1;
int speedx = 0;
int pos = 90;
void setup()
{
left.attach(leftpin); // attaches the servo on the A0 pin to the servo object
right.attach(rightpin); // attaches the servo on the A0 pin to the servo object
//speed adjusting forward
Spark.function("forward", Forward); //setpos // setPosition // original
//Caluclation Functions for position drive
/*
Spark.function("setpos", setPosition);
Spark.variable("getpos", &pos, INT);
*/
//---
//Backward default
Spark.function("backward", Backward);
Spark.function("turnright", TurnRight);
Spark.function("turnleft", TurnLeft);
//get a variable
//Spark.variable("getpos", &pos, INT); // "getpos", &pos, INT
//Spark.variable("getRightSpeed", getrightspeed, INT);
//LED Function
//Spark.function("led", ledControl); // registering spark function for led call and fucntion control
// active pins for LEDs
//pinMode(led1, OUTPUT);
//pinMode(led2, OUTPUT);
//initialize off
pinMode(PIN, OUTPUT);
}
void loop()
{
digitalWrite(PIN, HIGH);
delay(1000);
digitalWrite(PIN, LOW);
}
//example mapping
// no longer needed
/*
int setPosition(String posValue) {
pos = posValue.toInt();
//myservo.write(pos); this will do nothing, instead just route pos = speed and call forward function from here! It acts as the gateway!
return 0;
}
*/
int Forward(String speed){
//change value to int from string because string can only be passed to function
speedx = speed.toInt();
left.write(speedx);
right.write(speedx);
return 1;
}
int TurnLeft(String speed){
speedx = speed.toInt();
left.write(70);
right.write(110);
return 1;
}
int TurnRight(String speed){
speedx = speed.toInt();
left.write(110);
right.write(70);
return 1;
}
int Backward(String speed){
speedx = speed.toInt();
left.write(110); // must be > 90
right.write(110);
return 1;
}
/*
int ledControl(String command)
{
int state = 0;
//find out the pin number and convert the ascii to integer
int pinNumber = (command.charAt(1) - '0') - 1;
//Sanity check to see if the pin numbers are within limits
if (pinNumber < 0 || pinNumber > 1) return -1;
// find out the state of the led
if(command.substring(3,7) == "HIGH") state = 1;
else if(command.substring(3,6) == "LOW") state = 0;
else return -1;
// write to the appropriate pin
digitalWrite(pinNumber, state);
return 1;
}
*/
Here’s the other half, complete jaavscript and html code.
<!DOCTYPE HTML>
<html>
<body>
<!--
best version here
-->
<h1><b>Command App:</b></h1>
<!-- form here
We need to map 90 to 30 : 0 mph to 5 mph or 12 pts = 1 mph 6 pts = .5 mph 3 pts = .25 mph 1.5 pts = .125 mph
We then need to map 0 mph back to 90 - 30 for forward or 90 - 180 for backward function
-->
<h3>Set throttle speed</h3>
<p>30 = top speed forward</p>
<p>80 = slowest speed forward</p>
<p>110 = slowest speed backward</p>
<p>180 = fastest speed backward</p><br>
<input type="range" name="degBox" id="degBoxId" min="0" max="180" step="1" value="90" list="myData">
<!-- This adds the tick marks to the range but does not in Safari -->
<datalist id="myData">
<option value="0">
<option value="30">
<option value="60">
<option value="90">
<option value="120">
<option value="150">
<option value="180">
</datalist>
<br><br>
<button id="minusbutton">⇐ -5 °</button>
<button id="plusbutton">+5 ° ⇒</button>
<br><br>
<P>Throttle Speed: <span id="curPos"></span><br>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<!-- Javascript server side code -->
<script type="text/javascript">
//set credentials
// set functions to call
var deviceID = "53ff6e066667574845592267";
var accessToken = "6d3faea8e2c0d23c4fb78b1ca846c619855010ae";
var speed = 90; // default speed changed from 40
var currentCommand = '';
// USELESS
var fwd = "forward";
// DONT NEED THESE //
var tr = "turnright";
var tl = "turnleft";
var getFunc = "getpos";
var setFunc = "setpos";
// DONT NEED THESE //
/*
//DEAD LEGACY CODE //
window.setInterval(function() {
requestURL = "https://api.spark.io/v1/devices/" + deviceID + "/" + getFunc + "/?access_token=" + accessToken;
//Get form values
$.getJSON(requestURL, function(json) {
document.getElementById("curPos").innerHTML = json.result + "°";// this injects curPOS into the span ID!
document.getElementById("curPos").style.fontSize = "28px";
document.getElementById("degBoxId").value = parseInt(json.result);
});
}, 1500);*/
$('#degBoxId').val(speed); // sets any ID with degBoxId to value speed
// If i want to do multiple things use class. i.e. if i have multiple degree boxes and I want to set them.
// use class anywhere I want it to be set.
//Updates now for first update
$('body').on('keydown', function (event) { // whole page onclick
if (event.keyCode === 40) {
currentCommand = 'backward';
}
// arrow up
else if (event.keyCode === 38) {
currentCommand = 'forward';
}
// arrow left
else if (event.keyCode === 37) {
currentCommand = 'turnleft';
}
// arrow right
else if (event.keyCode === 39) {
currentCommand = 'turnright';
}
// request string
var requestURL = "https://api.spark.io/v1/devices/" + deviceID + "/" + currentCommand + "/";
// execution post of request string
$.post(requestURL, { params: speed, access_token: accessToken });
});
// like above block but for stopping. whenever I lift up on whatever arrow I have it stops
$('body').on('keyup', function () {
var requestURL = "https://api.spark.io/v1/devices/" + deviceID + "/" + currentCommand + "/";
$.post( requestURL, { params: 90, access_token: accessToken });
});
//whenever the slider changes, it will update the current position by re-assigning speed value
$('#degBoxId').on('change', function (event) {
speed = event.target.value;
$('#curPos').text(speed);//assigns ID #curPos the newly made speed
});
// decrementing down with fineAdjust function
$('#minusbutton').on('click', function (event) {
fineAdjust(-5);
});
// Incrementing
$('#plusbutton').on('click', function (event) {
fineAdjust(5);
});
// Used in input form. Gets curPos string element value, changes it to an integer
function fineAdjust(value) {
var setValue = speed + value; //adds last value plus this one
document.getElementById("degBoxId").value = setValue; // set degBoxId element value to setValue DISPLAY
speed = setValue;
//sp(setValue); //sets current position
}
/*
//passive function
function setValue(obj) {
var newValue = document.getElementById('degBoxId').value; // grabbing element by ID. ID finds element, then extracts the value!
speed = newValue; // call third function sparkSetpos, this will send the value to fwd . Starts with 90 aka zero
//Calling sparkSetPos(90);
document.getElementById("degBoxId").value = newValue;
}
*/
</script>
</body>
</html>
I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~Jordy
Try to do as little as possible inside you functions. Rather, have them set a flag which gets checked for in the main loop. That might improve some things.
OK. You don’t think that there’s a way to optimize even faster? Like, doublerobotics does a good telepresence job, but that’s likely because they have their own special cocktail of hardware, etc?
So I see some familiar code in the commented out parts of your code! That’s great–hope it helped.
I am about 0.125 of seconds from the Spark cloud, so anything I send to cloud and it sends to my core takes at least 0.25 seconds round-trip even if the processing in the cloud and core takes zero time. In reality, anything faster than about one function call per second and one variable read per second starts to have lag problems for me. If you are going to use the public cloud, I don’t think you are going to be able to “spam” the arrow keys as my kids would say. That said, 10 seconds of lag is weird and not explained yet–maybe your core is going off line or has some other long delay bug.
I am sure that this can be improved if you switch to a local cloud setup where the latency can much lower.
Or you could switch to local TCP or UCP connections with your own controller app.
I don’t see any logical explanation why it takes so long.
However, I experienced some weird timing errors a while ago and I managed to solve those with creating a delay loop which calls Spark.process(); ( @moors7 suggested that). Perhaps you can give that a shot.
I think your on to something here, bko (where I got my original code from on his servo post) hd a delay timer so that it didn’t flood requests, or something.
I think it has something to do with checking the cloud connection which should be done when you call delay() in automatic mode but in my case back then it seemed to fail.
Anyway, be right back
Edit:
This is the code:
void myDelay(unsigned long duration)
{
unsigned long start = millis();
while (millis() - start <= duration)
{
Spark.process();
}
}
@transcendrobotics Replace delay(1000); with myDelay(1000); in your code. Hope this works
void loop()
{
digitalWrite(PIN, HIGH);
delay(1000); //<--- Replace here!? I'm doing this because it gives some cushion on function responses each time it runs through?
digitalWrite(PIN, LOW);
}
Interestingly enough the standard delay() call does actually call spark.process() every so often. Not every loop like yours does @TheHawk1337 but every X seconds where I’ve forgotten X