Protothread help required.

Hi all,

I am hoping for a little assistance with what should (theoretically) be a very simple question.

I have some code which I have written/bodged.

In simple terms all I want to do is count how many times I have pressed a button and display the result on a webpage, however this is proving a little more challenging than I thought.

The code works perfectly… When a browser is not requesting a page. However whilst the arduino is sending data to the browser it will not pick up any button presses.

My theory is that if I run the code to pick up the presses in a separate thread to the code that submits the data to the browser it should solve this problem, after doing a little research I believe I can do this with protothreads?

But in all honesty as much as I read the protothreads tutorial I simply cannot understand the code enough to put it into place, can anyone help me?

Here is my code…

/*

 * Ethernet shield attached to pins 10, 11, 12, 13

 * +5v to Switch Pin 1
 * Switch Pin 2 to Analog Input *
 * Switch Pin 2 to Ground via 10k Resistor
 
 */

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 
  10,0,0, 177 };

#define pulse_received 0 
#define pulse_not_received 1

int pulse_active = 0;
int pulse_delay = 500;
int pulse_sensitivity = 500;
int pulse_sensitivity_mv = pulse_sensitivity*4.9;
int pulses_received = 0;
int reading_pin = 5;

int check_pulses()
{
 pulse_active = analogRead(reading_pin);
  if (pulse_active > pulse_sensitivity) return pulse_received; 
 return pulse_not_received;
}

Server server(80);

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
}

void loop()
{

// This is the start of the part I want in it's own thread           
switch (check_pulses())              
           {
             case pulse_received:
               {
               pulses_received++;
               delay(pulse_delay);
               break; 
               }
             case pulse_not_received:
               {
               break;
               }
            }
// This is the end of the part I want in it's own thread

  Client client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<meta http-equiv=\"refresh\" content=\"2\" >");
           client.print("Received ");
           client.print(pulses_received);
           client.print(" Pulses");
           client.print("
");
           client.print("Pin ");
           client.print(reading_pin);
           client.print(" is being monitored.");
           client.print("
");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}

Any help would be much appreciated and thanks in advance :slight_smile:

Not sure what a Protothread is. I would use an interrupt instead of analogRead. http://arduino.cc/en/Reference/AttachInterrupt

Can you explain why the pulse is being detected as an analogue value? It strikes me as more natural that this would be a digital input. Assuming it is in fact an alalogue reading then you would be to use a static variable to remember the previous state each time check_pulses() is called, and count a pulse only on the low–>high transition. If the analogue source has any noise in it, then you probably also want some hysteresis coded in. Roughly:

#define HYSTERESIS 50
#define PULSE_LOW_SENSITIVITY 500
#define PULSE_HIGH_SENSITIVITY (PULSE_LOW_SENSITIVITY + HYSTERESIS)

int check_pulses()
{
 static int old_state = 0;

 int reading;
 int state;
 int have_pulse;

 state = old_state;
 have_pulse = 0;

 /* Get the current reading
   */
 reading = analogRead(reading_pin);

  /* if the old_state is "on", then look to see if the new reading
    * has crossed the on-->off threshold
    */
  if (old_state != 0) {
      if (reading < PULSE_LOW_SENSITIVITY)
          state = 0;

  /* old state is off, look for an off-->on threshold crossing
    */
  } else {
      if (reading > PULSE_HIGH_SENSITIVITY)
          state = 1;
  }

 /* In the event that the state has gone from on-->off, we have
   * a pulse.  Otherwise, not.
   */
 if (old_state == 0 && state != 0) {

     // Here I could simply increment a global pulse count instead of returning this state
     have_pulse = 1;
 }

 old_state = state;

 return have_pulse;
}

If the pulse source is capable of switch bounce, then it should also look for a time period to expire before reporting another transition. That would mean recording the time of a transition and ignoring any apparent transitions until some time has passed.

Pauly: I would use an interrupt instead of analogRead. http://arduino.cc/en/Reference/AttachInterrupt

That sounds like the smart answer to me.

Thanks for all the feedback:)

I'll do a little research into the interrupts, however for the final product this could be a nuisance as I believe I can only have 6 inputs on a Mega.

I should have probably gone in to a little more detail on the final product requirements...

My task is to monitor some simple switches on the end of a wire ranging from 10-400 metres. Each site will have between 20-40 of these switches, each switch has it's own dedicated cable pair. Currently we are using the ADAMS-6050 unit, these have 12 inputs and work perfectly but weigh in at £180+VAT each!

I chose analog as I was under the impression it would give me a little more room to change the tolerances due to the cable lengths, but I guess this can be done via digital too? If that is the case then digital would be much better due to the input count.

I am simply trying to find a cheaper solution to the ADAMS units, which seem to be a huge overkill.