Blinking an LED *and* rotating a servo

I’ve been able to blink an led, and rotate a servo separately.

Now I’m trying to do both, but I’m missing something: either the LED blinks, or the servo moves, but I can’t control them both separately. I’m sure I’m doing something fundamentally wrong.

Any help/advice appreciated.

thanks!

DC

Here’s my code, with some commentary from one of the Particle examples:

Servo serv;
int pos = 0;
int led1 = D6;
int led2 = D7;


void setup() {

  serv.attach(D0);
    Particle.function("setpos", setPos);
    Particle.variable("getpos", &pos, INT);
    
      // Here's the pin configuration.
   pinMode(led1, OUTPUT);
   pinMode(led2, OUTPUT);

   // We are also going to declare a Particle.function so that we can turn the LED on and off from the cloud.
   Particle.function("led",ledToggle);
   // This is saying that when we ask the cloud for the function "led", it will employ the function ledToggle() from this app.

   // For good measure, let's also make sure both LEDs are off when we start:
   digitalWrite(led1, LOW);
   digitalWrite(led2, LOW);


}

void loop() {
}

int setPos(String pstn) {
    pos = pstn.toInt();
    serv.write(pos);
    return pos;

}

// We're going to have a super cool function now that gets called when a matching API request is sent
// This is the ledToggle function we registered to the "led" Particle.function earlier.

int ledToggle(String command) {
    /* Particle.functions always take a string as an argument and return an integer.
    Since we can pass a string, it means that we can give the program commands on how the function should be used.
    In this case, telling the function "on" will turn the LED on and telling it "off" will turn the LED off.
    Then, the function returns a value to us to let us know what happened.
    In this case, it will return 1 for the LEDs turning on, 0 for the LEDs turning off,
    and -1 if we received a totally bogus command that didn't do anything to the LEDs.
    */

    if (command=="on") {
        digitalWrite(led1,HIGH);
        digitalWrite(led2,HIGH);
        return 1;
    }
    else if (command=="off") {
        digitalWrite(led1,LOW);
        digitalWrite(led2,LOW);
        return 0;
    }
    else {
        return -1;
    }
}

And here’s what I’ve got on my website.

<p>This is an attempt to combine servo code and blink an LED code. And then combine the blink and the continuous rotation web code.</p>


<hr />
<style type="text/css">body {
      margin: 1em auto;
      max-width: 45em;
      padding: 0.8em;
      background: white;
    }
</style>
<h2>Turn the light on and off</h2>

<form>
<p><input type="radio" value="off" onclick="showValue(this.value)" name="led" /> Off
<input type="radio" value="on" onchange="showValue(this.value)" name="led"/> On 

</p>
</form>

<script type="text/javascript">
    function showValue(newValue) {
    //  document.getElementById("range").innerHTML=newValue;
      var request = new XMLHttpRequest();
      var dev_id = '2a0031000847353138383138';
      var access = '55124b34fd82a5e272dc8772438e81e14213710e';
      var data = 'params='+newValue+'&access_token='+access;
      var url = 'https://api.particle.io/v1/devices/'+dev_id+'/led/';
      request.open('POST', url, true);
      request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
      request.send(data);
    }
    </script></p>


<h2>Continuous servo control</h2>

<style type="text/css">body {
      margin: 1em auto;
      max-width: 45em;
      padding: 0.8em;
      background: white;
    }
</style>

<form>
<p><input type="radio" value="93" onclick="showValue(this.value)" name="servo" /> Off
<input type="radio" value="0" onchange="showValue(this.value)" name="servo"/> On (right)
<input type="radio" value="180" onchange="showValue(this.value)" name="servo"/> On (left)
</p>
</form>

 <script type="text/javascript">
    function showValue(newValue) {
    //  document.getElementById("range").innerHTML=newValue;
      var request = new XMLHttpRequest();
      var dev_id = '2a0031000847353138383138';
      var access = '55124b34fd82a5e272dc8772438e81e14213710e';
      var data = 'params='+newValue+'&access_token='+access;
      var url = 'https://api.particle.io/v1/devices/'+dev_id+'/setpos/';
      request.open('POST', url, true);
      request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
      request.send(data);
    }
    </script></p>

@dcdenison

<form>
<p><input type="radio" value="off" onclick="showValue(this.value)" name="led" /> Off
<input type="radio" value="on" onchange="showValue(this.value)" name="led"/> On 

and

&lt;form&gt;
&lt;p&gt;&lt;input type="radio" value="93" onclick="showValue(this.value)" name="servo" /&gt; Off
&lt;input type="radio" value="0" onchange="showValue(this.value)" name="servo"/&gt; On (right)
&lt;input type="radio" value="180" onchange="showValue(this.value)" name="servo"/&gt; On (left)
&lt;/p&gt;
&lt;/form&gt;

I’m not an HTML person, but both radio buttons call the same function…

both functions are defined wht the same name: showValue().

I’d take a look at changing one of the functions’ names and changing the corresponding function call to refer to the new name.

EDIT: You may have done this already, but remember to obfuscate/redact your deviceID and access token. Armed with both, a bad guy can spin your servo!

FYI, I recently cobbled together a home automation web-app that uses a mix of my Vera home controller commands (HTTP GETs) and a few Particle functions.

I designed it for mobile phone (width) and the app allows guests to control the thermostat and a few other things in/around the guest house; they just access a local server once they are on my network.

Looks like this:

and:

Maybe you (or someone can) get something out of this… It does not “Get” any settings yet, rather just a dumb push of commands. Like I said, I’m HTML impaired.

I recall ti tok a while to work out the div’s for the buttons!

html/Java:

<!DOCTYPE html>

<html lang="en">
  <head>
  	<title>Guest Home Controller</title>
  	<link rel="stylesheet" type="text/css" href="style.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
	<style>
	img {
    	-webkit-filter: blur(5px); /* Chrome, Safari, Opera */
    	filter: blur(5px);
	}
	.button {
		background-color: #999999;
		border: none;
		color: white;
		padding: 5px 10px;
		text-align: center;
		text-decoration: none;
		display: inline-block;
		font-size: 16px;
		margin: 4px 2px;
		cursor: pointer;
		width: 80px;
	}
	</style>

<script type="text/javascript">


function lightPower(newValue, lightID) 
{
	var request = new XMLHttpRequest();
	var url = 'http://10.0.1.25:3480/data_request?id=action&output_format=xml&DeviceNum='+lightID+'&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue='+newValue;
	request.open('GET', url);
	request.send();
}

function sendDimmerValue()
{
	var newValue = document.getElementById("range").innerHTML;
	var request = new XMLHttpRequest();
	var dev_id = 'DEVICE_ID_HERE';
	var access = 'ACCESS_TOKEN_HERE';
	var data = 'params='+newValue+'&access_token='+access;
	var url = 'https://api.particle.io/v1/devices/'+dev_id+'/setDimLevel/';
	request.open('POST', url, true);
	request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
	request.send(data);
}

function showValue(newValue)
{
 	document.getElementById("range").innerHTML = newValue;
}

function showMainTstatValue(newValue)
{
 	document.getElementById("range2").innerHTML = newValue;
}

function tstatUP()
{
	var newValue = document.getElementById("range2").innerHTML;
	newValue++;
	if(newValue > 86) newValue = 86;
	document.getElementById("range2").innerHTML = newValue;
}

function tstatDN()
{
    var newValue = document.getElementById("range2").innerHTML;
	newValue--;
	if(newValue < 72) newValue = 72;
	document.getElementById("range2").innerHTML = newValue;
}

function sendMainTstatValue()
{
	var newValue = document.getElementById("range2").innerHTML;
	var request = new XMLHttpRequest();
	var url = 'http://10.0.1.25:3480/data_request?id=action&output_format=xml&DeviceNum=3&serviceId=urn:upnp-org:serviceId:TemperatureSetpoint1_Cool&action=SetCurrentSetpoint&NewCurrentSetpoint='+newValue;
	request.open('GET', url);
	request.send();
}

function showGuestHouseTstatValue(newValue)
{
 	document.getElementById("range3").innerHTML = newValue;
}


function guestTstatUP()
{
	var newValue = document.getElementById("range3").innerHTML;
	newValue++;
	if(newValue > 86) newValue = 86;
	document.getElementById("range3").innerHTML = newValue;
}

function guestTstatDN()
{
    var newValue = document.getElementById("range3").innerHTML;
	newValue--;
	if(newValue < 72) newValue = 72;
	document.getElementById("range3").innerHTML = newValue;
}

function sendGuesTstatValue()
{
	var newValue = document.getElementById("range3").innerHTML;
	var request = new XMLHttpRequest();
	var url = 'http://10.0.1.26:3480/data_request?id=action&output_format=xml&DeviceNum=79&serviceId=urn:upnp-org:serviceId:TemperatureSetpoint1_Cool&action=SetCurrentSetpoint&NewCurrentSetpoint='+newValue;
	request.open('GET', url);
	request.send();
}

function PhoneyPower(newValue) 
{
	var request = new XMLHttpRequest();
	var dev_id = 'DEVICE_ID_HERE';
	var access = 'ACCESS_TOKEN_HERE';
	var data = 'params='+newValue+'&access_token='+access;
	var url = 'https://api.particle.io/v1/devices/'+dev_id+'/phoneyPower/';
	request.open('POST', url, true);
	request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
	request.send(data);
}
</script>

</head>

<body>
	<div id="container">
		<div id="header">
		
		  <h1><p>Guest House<br />Home Controller</p></h1>
		  
		</div>
		
		<div id="rooms">
		
			<div id="kitchen">
			
				<hr size="10" NOSHADE>			
				<h1><p align="center">Kitchen</p></h1><hr />
			  	<h2>Kitchen Counter LEDs</h2>
				<input id="myRange" type="range" style="width: 325px; height 40px" min="0" max="100" value="0" step = "5" oninput="showValue(this.value+ '%')" onchange="showValue(this.value+ '%')">
				<span id="range">0%</span>
				<br/> <br/>
				<input type="button" onclick="sendDimmerValue()" value = UPDATE />
				<hr />
				<h2>Accent Lights</h2>
				<p><input type="radio" value="0" onclick="lightPower(this.value, 10)" name="led" /> Off
				<input type="radio" value="1" onclick="lightPower(this.value, 10)" name="led"/> On 
				</p>

			</div>
			
		    <div id="family">
		    
				<hr size="10" NOSHADE>
				<h1><p align="center">Family Room</p></h1><hr />
			  	<h2>Accent Lights</h2>
				<p><input type="radio" value="0" onclick="lightPower(this.value, 27)" name="led" /> Off
				<input type="radio" value="1" onclick="lightPower(this.value, 27)" name="led"/> On 
				</p>	    
		    
		    </div>
			
			<div id="cabana">
			
				<hr size="10" NOSHADE>
				<h1><p align="center">Cabana</p></h1>
				<hr />
				
				<div id="mainThermostat">
				
					<div id="tstatSlider">
				
						<h2>Thermostat Setting</h2>
						<input id="tstatRange" type="range" style="width: 200px; height 40px" min="72.0" max="86.0" value="76" step = "0.5" oninput="showMainTstatValue(this.value)" onchange="showMainTstatValue(this.value)">
						<span id="range2">76.0</span>&deg;F
						<br/> <br/>
						<input type="button" onclick="sendMainTstatValue()" value = SUBMIT />
						<br /><br />
					</div>
					
					<div id="tstatButtons">
						<br />
						<br />
						<input type="button" class="button" value="UP" onclick="tstatUP()">
						<br />
						<input type="button" class="button" value="DOWN" onclick="tstatDN()">
					</div>

				
				</div>
				
				<div id="cabanaElements">
					
					<hr />
					<h2>PhoneyTV Cabana</h2>
					<p><input type="radio" value="0" onclick="PhoneyPower(this.value)" name="led" /> Off
					<input type="radio" value="1" onclick="PhoneyPower(this.value)" name="led"/> On 
					</p>

					<hr />
					<h2>Cabana Nightstand Light</h2>
					<p><input type="radio" value="0" onclick="lightPower(this.value, 100)" name="led" /> Off
					<input type="radio" value="1" onclick="lightPower(this.value, 100)" name="led"/> On 
					</p>

					<hr />
					<h2>Cabana Slider Light</h2>
					<p><input type="radio" value="0" onclick="lightPower(this.value, 111)" name="led" /> Off
					<input type="radio" value="1" onclick="lightPower(this.value, 111)" name="led"/> On </p>
				
					<hr />
					<h2>Cabana Patio Light</h2>
					<p><input type="radio" value="0" onclick="lightPower(this.value, 103)" name="led" /> Off
					<input type="radio" value="1" onclick="lightPower(this.value, 103)" name="led"/> On 
					</p>
					
				</div>
		
			</div>
			
			<div id="guesthouse">
			    <hr size="10" NOSHADE>
			    <h1><p align="center">Guest House</p></h1>
			    <hr />
			    
				<div id="guestThermSlider">
					<h2>Thermostat Setting</h2>
					<input id="tstatRange" type="range" style="width: 200px; height 40px" min="72.0" max="86.0" value="76" step = "0.5" oninput="showGuestHouseTstatValue(this.value)" onchange="showGuestHouseTstatValue(this.value)">
					<span id="range3">76.0</span>&deg;F
					<br/> <br/>
					<input type="button" onclick="sendGuesTstatValue()" value = SUBMIT />
					<br/><br/>
				</div>
				
				<div id="guestThermButtons">
					<br />
					<br />
					<input type="button" class="button" value="UP" onclick="guestTstatUP()">
					<br />
					<input type="button" class="button" value="DOWN" onclick="guestTstatDN()">
				</div>
				
			</div>
			
		<div id="footer">
			<div id="footer-content"><p>Copyright &copy; 2016<br />Jim Brower</p></div>
		</div>
		
		<div id="gutter">
			<a href="mailto:someone@gmail.com?subject=Suggestions">Send suggestions for improvements<a>
		</div>
		
	</div>
			
</body>

</html>

and the CSS file:

#body {
	width: 375px;
}

#container {
	
	width: 375px;
	margin-left: auto;
	margin-right: auto;
	
}

#header {
  padding: 50px;
  background-image: url("GreyBrick.jpg");
  background-position: center center;
  text-align: center;
  color: white;
}

#rooms{

}

#kitchen{

}

#cabana{

}

#tstatSlider {
	float: left;
}

#tstatButtons {
  float: right;
  
}
#cabanaElements {
	clear: left;
}

#family {

}

#guesthouse {

}

#guestThermSlider{
	float: left;
}

#guestThermButtons{
  float: right;
}

#footer{
  clear: left;
  padding: 150px;
  background-image: url("PaulRevere.jpg");
  background-position: center center;
}

#footer-content {
    color: white;
    position: relative;
    top: 160px;
    left: -140px;
}

Thanks! I knew I was making a basic mistake.

This is really helpful.

BTW, does the “Lowell” mean that you live north of Boston?

DC

This looks really cool. And the HTML is better than I’ve got going so far.

Let me know if you want to try to adapt these to some Particle devices.

DC

I went to ULowell for my undergrad, yes but I’ve moved since those days (note statue of Paul Revere in my webpage, I took that when I lived in the Back Bay).

In the HTML file you will see in the Kitchen <div id="kitchen"> the <h2>Kitchen Counter LEDs</h2>and in the Cabana the <h2>PhoneyTV Cabana</h2> both call Particle functions.

The LEDs are actually two photons talking to each other… set one LED strip and it instructs the other to follow along.

two functions:

function sendDimmerValue()

and

function PhoneyPower(newValue)

are both talking Particle.

Like I said, I suck at HTML, on this I used the brute force method.

I would have liked to understand better how to pass an argument to the Thermostat functions and avoid having to have a set of functions for each thermostat, for example.

I’m going to spend some time on the calls that get the state of the devices and see if I can hook this webpage to some actual data, somehow. I could use help with that, I’m sure!

Yeah, the Lowell + Paul Revere usually = Boston area. : )

After I fix my code (thanks again!) I may take a crack at adapting some of your functions (with full credit, of course). I’ll keep you posted.

I also have a few Particle projects that are working pretty well. I’ll share those when I get them in slightly better shape.

Thanks again for the info.

DC

1 Like