Problem of web control

I am currently try to use the web control led code template to control the motor. The setup is to connect the photon with L293D motor module . My logic is :smile:

When I click “on” in html = the motor moves clockwise & anticlockwise motion interchanging
When I clixk “off” in html = it stops

the code is like

// -----------------------------------
// Controlling LEDs over the Internet
// -----------------------------------

// First, let's create our "shorthand" for the pins
// Same as in the Blink an LED example:
// led1 is D0, led2 is D7

int led1 = D2;
int led2 = D3;

// Last time, we only needed to declare pins in the setup function.
// This time, we are also going to register our Spark function

void setup()
{

   // Here's the pin configuration, same as last time
   pinMode(led1, OUTPUT);
   pinMode(led2, OUTPUT);

   // We are also going to declare a Spark.function so that we can turn the LED on and off from the cloud.
   Spark.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);

}


// Last time, we wanted to continously blink the LED on and off
// Since we're waiting for input through the cloud this time,
// we don't actually need to put anything in the loop

void loop()
{
   // Nothing to do here
}

// 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" Spark.function earlier.


int ledToggle(String command) {
    /* Spark.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") {
        for (int x =0 ; x < 1000 ; x++){
        digitalWrite(led1,HIGH);
        digitalWrite(led2,LOW);
        delay (500);
        digitalWrite(led1,LOW);
        digitalWrite(led2,HIGH);
        delay (500);
        }
    }
    else if (command=="off") {
        digitalWrite(led1,LOW);
        digitalWrite(led2,LOW);
        return ;
    }
    
}

However, when I tried to operate, like first i click on, it can perform correctly with interchanging direction, but i try to click off, it stops for 1 second and continue to start moving interchanging

May I ask whether i can stop the motion by improving the code?

I didn’t test it but give it go. The main loop toggles the output if run is high. So an off command will disable it within 500ms. I didn’t put the 1000 count back in though, but it should get you started.

Edit: Oops. Forgot to stop it. So, I added the count too.

int led1 = D2;
int led2 = D3;
bool run;
bool toggle;
int count;

void setup()
{
     pinMode(led1, OUTPUT);
     pinMode(led2, OUTPUT);

     Spark.function("led", ledToggle);

     digitalWrite(led1, LOW);
     digitalWrite(led2, LOW);
}

void loop()
{
   if(run)
   {
      if(millis() - last >= 500)
      {
        last = millis();
        if(toggle = !toggle)
        {
           digitalWrite(led1, HIGH);
           digitalWrite(led2, LOW);
        }
        else
        {
           digitalWrite(led1, LOW);
           digitalWrite(led2, HIGH);
        }
        if--count == 0)
           run = false;
   }
}

int ledToggle(String command)
{
   run = (command == "on") ? true : false;
   if(run)
   {
        count = 2000;
    }
   else
   {
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
   }
}
1 Like

@leslietsz, when you call on once, you are starting a 1000x (500+500) millisecond loop - more than quater of an hour!
By calling delay() inside that loop you also implicitly call the cloud task once per second which allows cloud calls to be processed (e.g. your stop call), but you are still trapped inside your 1000sec loop, which will carry on doing its job once delay() and its implicitly triggered task return.

So a rule of thumb:
Don’t use long delays or long running loops inside a Particle.function()

Also use Particle instead of the depricated Spark.

And when a function is declared int someFunction() it has to return an int!

2 Likes

Thank you guys, it works, but I have one question , is that anyway to modify the html coding , such that it will not show the return value page, after i click it?

Yup, use javascript. There’s an SDK in the docs, and there are tutorials in the tutorials category.
I’ve got a page over here that does just that.

Hi, may i know which tutorial is suitatble? Thanks

Had you looked, you would've known...

This uses the SDK for function calls, right click to see the source: http://jordymoors.nl/particle/demos/function_button.html

1 Like

Thanks I will have a look

Dear Moors7,

I have read the tutorials, but i dont quite understand the coding, for my case, I have 4 buttons, representing 4 direction.\

When I click the button, it will post the value to the server, right?

For function functionPost(functionName, functionArgument) this part, should i use

document.getElementById(’ object’).value to find the value?

Also, spark.callFunction(deviceID, functionName, functionArgument, callback); , it only contains deviceID, so no access token is required?

I am really very very beginner in programming, so sorry for those troublesome , :smile:

Here is my coding

Previously I have asked the question on web control for my project, thanks to some nice people, I can finally build my code and test the website control

I am currently try to use the web control led code template to control the motor. The setup is to connect the photon with L293D motor module .

When I click “foward” in html = the motor moves clockwise & anticlockwise motion interchanging
When I click “left” in html = it moves in one side, stop and start back
When I click “right” in html = it moves in another side, stop and start back
When I click stop, it stops

Here is the coding

int led1 = D2;
int led2 = D3;
bool forward ;
bool left;
bool right;
bool toggle;
int count;
int last = 0;

void setup()
{

   pinMode(led1, OUTPUT);
   pinMode(led2, OUTPUT);    

   Particle.function("led",ledToggle);

   digitalWrite(led1, LOW);
   digitalWrite(led2, LOW);

}

 void loop()
{
   if(forward)
   {
      if(millis() - last >= 500)
      {
        last = millis();
        
        if(toggle = !toggle)
        {
           digitalWrite(led1, HIGH);
           digitalWrite(led2, LOW);
        }
        else
        {
           digitalWrite(led1, LOW);
           digitalWrite(led2, HIGH);
        }
        if(--count == 0){
           forward = false;
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        }
      }
   }
   
   if(left)
   {
      if(millis() - last >= 500)
      {
        last = millis();
        
        if(toggle = !toggle)
        {
           digitalWrite(led1, HIGH);
           digitalWrite(led2, LOW);
        }
        else
        {
           digitalWrite(led1, LOW);
           digitalWrite(led2, LOW);
        }
        if(--count == 0){
           left = false;
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        }
      }
   }
   
   if(right)
   {
      if(millis() - last >= 500)
      {
        last = millis();
        
        if(toggle = !toggle)
        {
           digitalWrite(led1, LOW);
           digitalWrite(led2, HIGH);
        }
        else
        {
           digitalWrite(led1, LOW);
           digitalWrite(led2, LOW);
        }
        if(--count == 0){
           right = false;
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        }
      }
   }
}

int ledToggle(String command) {
if(command == "forward")
   {
        forward = true;
        count = 2000;
        return 0;
    }
   else if(command == "left")
   {
       left = true;
       count = 2000;
        return -1;
   }
   else if(command == "right")
   {
       right = true;
       count = 2000;
        return 2;
   }
   else
   {
       forward = false ;
       left = false;
       right = false;
       
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        return 1;
   }
}

The html file coding is as follow

/* Paste the code between the dashes below into a .txt file and save it as an .html file. Replace your-device-ID-goes-here with your actual device ID and your-access-token-goes-here with your actual access token.

---------------------------
<!-- Replace your-device-ID-goes-here with your actual device ID
and replace your-access-token-goes-here with your actual access token-->
<!DOCTYPE>
<html>
  <body>
  <center>
  <br>
  <br>
  <br>
  <form action="https://api.particle.io/v1/devices/xxxxxx/led?access_token=yyyyyy" method="POST">
    Tell your device what to do!<br>
    <br>
    <input type="radio" name="args" value="forward">Forward motion.
    <br>
    <input type="radio" name="args" value="left">Left motion.
    <br>
    <input type="radio" name="args" value="right">Right motion.
    <br>
    <input type="radio" name="args" value="stop">Stop motion.
    <br>
    <br>
    <input type="submit" value="Do it!">
  </form>
  </center>
  </body>
</html>
---------------------------
*/

I can use html file to run it, however, it is quite troublesome to have the feedback message each time I choose the action

Thanks to Moors7, he provided a tutorial from bko,

Tutorial: Spark Variable and Function on One Web Page

Also here

Controlling the Spark Core pins with webpage buttons

I still cannot understand the java programming code, can anyone please teach me how to implement it?

Thanks

Please don’t open new topics for the same questions, it gets confusing.

That said, give this HTML a try, and see if you understand it. Enter your DeviceID where it’s declared. Then, open the page, log in with your Particle credentials, and press the buttons :smile:
If there’s something you don’t understand, feel free to ask, but please try to keep that to this topic, no need to open new ones.

<html>
  <head>
      <title>Spark function buttons Example</title>
	  <script src="http://cdn.jsdelivr.net/sparkjs/1/spark.min.js"></script>
  </head>

  <body>
    <div id="login">
		<input type="email" class="form-control" placeholder="Emai" id="email"> </br>
		<input type="password" class="form-control" placeholder="Password" id="password">
		</br>
		<button type="button" onclick="login()">Login</button>
	</div>
    <button type="button" onclick="functionPost('led', 'forward')">Forward</button>
    <button type="button" onclick="functionPost('led', 'left')">Left</button>
	<button type="button" onclick="functionPost('led', 'right')">Right</button>
    <button type="button" onclick="functionPost('led', 'stop')">Stop</button>
    
    
    
    <script>
      //you can use your accesstoken, or your email/passsword to log in. Uncomment accordingly below.

      //var userAccessToken = "blabla";
      var deviceID = "deviceID here";
      
      // callback to be executed by each core
      var callback = function(err, data) {
        if (err) {
          console.log('An error occurred:', err);
        } else {
          console.log('Device action successfull:', data);
        }
      };
	  
	
      function functionPost(functionName, functionArgument){
        // The function needs to be defined  in the firmware uploaded to the
        // the Spark core/Particle photon and registered to the Particle cloud, same thing we do
        // with variables. You pass along the name of the function and the params.
        spark.callFunction(deviceID, functionName, functionArgument, callback);  
      }	  
  
      spark.on('login', function(response) {           
        console.log(response);
      });
	  
	  function login(){
        emailInput = document.getElementById('email');
        passwordInput = document.getElementById('password');
        
		console.log(emailInput.value + ", " + passwordInput.value);
		spark.login({ username: emailInput.value, password: passwordInput.value });
		
        emailInput.value = '';
        passwordInput.value = '';
      }
	  
      // Uncomment a line below depending on your preferred log-in method.   
      //spark.login({ username: 'email@example.com', password: 'password' });  
      //spark.login({ accessToken: userAccessToken });
      
    </script>
  </body>
</html>
2 Likes

Dear Moors7,

I have tested with your script, however, it shows a blank page when I turn on the html file, may I know what is happening?

Updated : My fault, I have tested and it works thank you!

1 Like

Dear CuriousTech, I am not quite understand the toggle usage, can you please tech me?

A toggle flips a bool each time. Using the logical not (!) like bool = !bool; it will flip the logical state of the variable each time it executes. It can also be used for if expressions as well, or any logic, like

fwd = !fwd;
DigitalWrite(pin1, fwd);
DigitalWrite(pin2, !fwd);

So each time fwd will be reversed. But that assumes HIGH and LOW are the same as true and false, so it would be safer as

DigitalWrite(pin1, fwd ? HIGH:LOW);
DigitalWrite(pin2, fwd ? LOW:HIGH);

In the code you provided, is that mean
at first 500ms

if (Toggle = !Toggle) mean toggle value is flip from HIGH to LOW, it execute HIGH,LOW in 2 pins

then for next 500ms

I dont understand how to execute the else function

Let me unpack it a little more and remove the flip from the if condition so it’s easier.

    toggle = !toggle; // flips the boolean (true/false) value each time
    if(toggle == true) // do this if true
    {
       digitalWrite(led1, HIGH);
       digitalWrite(led2, LOW);
    }
    else // do this if false
    {
       digitalWrite(led1, LOW);
       digitalWrite(led2, HIGH);
    }

So it should start out false, so it will be true the first time it runs. You could set the state of toggle to false in the ledToggle function to set it up though. But it will have up to 500ms delay if it was turned off and back on in less than 500ms.

Thank you very much, it looks much better to understand

//[quote="leslietsz, post:12, topic:19262"]
if(toggle = !toggle)
        {
           digitalWrite(led1, HIGH);
           digitalWrite(led2, LOW);
        }
        else
        {
           digitalWrite(led1, LOW);
           digitalWrite(led2, HIGH);
        }

An even easier to understand version IMHO would be

bool state;
...
  state = !state;  // flip or toggle the current state 
  // since true is equivalent HIGH and false is equivalent LOW, just use it
  digitalWrite(led1, state);  // same as state
  digitalWrite(led2, !state); // invers state

I see @CuriousTech had already shown you that :+1:

1 Like