Go Down

Topic: Knop via een webbrowser indrukken en na 100 ms automatisch "los laten" (Read 503 times) previous topic - next topic

johnvanvliet

Goedendag,

Dit is mijn eerste vraag op dit forum, omdat ik al een tijdje aan het proberen ben om via een knop in een webbrowser, een relais welke aangesloten zit op de arduino uno, aan te sturen. Nu lukt me dit wel, echter de knop (in de webbrowser) blijft in gedrukt en daardoor blijft ook het relais bekrachtigd.

Wat ik wil is dat ik via een webbrowser een knop in druk m.b.v. de muis, dat de tekst op de knop verandert naar "Uit", er een relais via een arduino uno bekrachtigd wordt en dat na 100 ms de knop in de webbrowser automatisch "los gelaten"wordt en daarmee ook de aansturing van het relais.

Kan iemand mij een schop in de goede richting geven?



/*
* John
*/

#include <SPI.h>                                     // Initialize the Serial Peripheral Interface library.
#include <Ethernet.h>                              // Initialize the Ethernet server library

byte mac[] = {
0x90, 0xA2, 0xDA, 0x0E, 0xCD, 0x5F };      // Enter a MAC address and IP address for your controller below.
IPAddress ip(192,168,2, 150);                    // The IP address will be dependent on your local network:

EthernetServer server(80);                        // Initialize the Ethernet server library
                                                           // with the IP address and port you want to use
                                                           // (port 80 is default for HTTP):                                                          

String relay1State = "Uit";                        // Relay 1 state and pin
const int relay1 = 4;
String relay2State = "Uit";                        // Relay 2 state and pin
const int relay2 = 5;


char linebuf[80];                                      // Client variables
int charcount=0;

void setup() {

pinMode(relay1, OUTPUT);                        // Relay 1 module prepared
digitalWrite(relay1, HIGH);  
pinMode(relay2, OUTPUT);                        // Relay 2 module prepared
digitalWrite(relay2, HIGH);

Serial.begin(9600);                                  // Open serial communication at a baud rate of 9600


Ethernet.begin(mac, ip);                            // start the Ethernet connection and the server:
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

                                                             // Display dashboard page with on/off button for relay
                                                           
void dashboardPage(EthernetClient &client) {
client.println("<!DOCTYPE HTML><html><head>");
client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body>");                                                            
client.println("<h3>Garagedeur openen via IntraNet - <a href=\"/\">Refresh</a></h3>");

client.println("<h4>Relais 1 - Status: " + relay1State + "</h4>");    // Genereert de knoppen Aan/Uit van relais 1
  if(relay1State == "Uit"){                          // Als relais 1 aangestuurd wordt, staat er op de knop "Aan"
  client.println("<a href=\"/relay1on\"><button>Aan</button></a>");
}
  else if(relay1State == "Aan"){                   // Als relais 1 NIET aangestuurd wordt, staat er op de knop "Uit"
  client.println("<a href=\"/relay1off\"><button>Uit</button></a>");                                                                    
}
client.println("<h4>Relais 2 - Status: " + relay2State + "</h4>");    // Genereert de knoppen Aan/Uit van relais 2
  if(relay2State == "Uit"){                           // Als relais 2 aangestuurd wordt, staat er op de knop "Aan"
  client.println("<a href=\"/relay2on\"><button>Aan</button></a>");
}
  else if(relay2State == "Aan"){                   // Als relais 2 NIET aangestuurd wordt, staat er op de knop "Uit"
  client.println("<a href=\"/relay2off\"><button>Uit</button></a>");                                                                    
}
client.println("</body></html>");
}


void loop() {
                                                               // listen for incoming clients
EthernetClient client = server.available();
if (client) {
  Serial.println("new client");
  memset(linebuf,0,sizeof(linebuf));
  charcount=0;
                                                                // an http request ends with a blank line
  boolean currentLineIsBlank = true;
  while (client.connected()) {
    if (client.available()) {
     char c = client.read();
                                                                 //read char by char HTTP request
      linebuf[charcount]=c;
      if (charcount<sizeof(linebuf)-1) charcount++;
                                                                 // if you've gotten to the end of the line (received a newline
                                                                 // character) and the line is blank, the http request has ended,
                                                                 // so you can send a reply
      if (c == '\n' && currentLineIsBlank) {
        dashboardPage(client);
        break;
      }
      if (c == '\n') {
        if (strstr(linebuf,"GET /relay1off") > 0){
          digitalWrite(relay1, HIGH);
          relay1State = "Uit";
        }
        if (strstr(linebuf,"GET /relay1on") > 0){
          digitalWrite(relay1, LOW);
          relay1State = "Aan";
        }
        if (strstr(linebuf,"GET /relay2off") > 0){
          digitalWrite(relay2, HIGH);
          relay2State = "Uit";
        }
        else if (strstr(linebuf,"GET /relay2on") > 0){
          digitalWrite(relay2, LOW);
          relay2State = "Aan";
        }
                                                                   // you're starting a new line
        currentLineIsBlank = true;
        memset(linebuf,0,sizeof(linebuf));
        charcount=0;          
      }
      else if (c != '\r') {
                                                                   // you've gotten a character on the current line
        currentLineIsBlank = false;
      }
    }
  }
                                                                   // give the web browser time to receive the data
  delay(1);
                                                                   // close the connection:
  client.stop();
  Serial.println("client disonnected");
}
}




Bij voorbaat dank,

John

MAS3

Hoi johnvanvliet, welkom !

Wanneer je de relais weer uit wil hebben, moet je ze uitzetten.
Ik zie wel code die je relais uit kunnen zetten, maar heb geen idee waar de aansturing daarvan precies vandaan komt.
Dat komt omdat ik (nog) niet zo goed ben in het lezen van HTML .
Ik zie een functie genaamd dashboardPage, waar de knoppen gemaakt worden.
Maar wanneer deze knoppen gemaakt worden, word gekeken welke staat de knoppen hebben, en worden ze schijnbaar altijd naar de andere stand gezet.
Het commentaar dat in deze functie staat, klopt niet met wat er in de betreffende regel gebeurt, dus daar word ik niet erg mee geholpen.

Wat ik in loop() zie gebeuren (regel 90), is dat uit je webpagina op 1 of andere wijze de waarde "GET /relay1off" krijgt, of GET /relay1on.
Daar doe je dan wat mee.

Maar uit je verhaal begrijp ik dat je dat zo helemaal niet wil doen.
Wat je wil, is dat wanneer virtuele knop 1 word ingedrukt, je 100mS iets gaat doen.
Dus wanneer die actie eenmaal gestart is, kun je dat niet meer ongedaan maken.
Daarom kun je aan relay1State een extra handeling hangen onder de voorwaarde dat die knop ooit is ingedrukt.
Die handeling is het starten en bijhouden van een timer.
Wanneer die timer verlopen is, zet je dus je relais weer uit.

De ongein bij dit projectje is, dat je die timer niet kunt laten lopen en verder niets doen.
Want dan ziet bijvoorbeeld de websitegebruiker niet dat ie de knop heeft ingedrukt.

Daarom is dit het ideale (en noodzakelijke) moment om de blink without delay sketch (klik!) te gaan bestuderen en doorgronden.
Wanneer je dat onder controle hebt, kun je in je site laten zien dat de knop is ingedrukt terwijl de timer aan het verlopen is; het is dan bijna alsof je aan het multitasken bent

Na het verlopen, kun je dus je relais gewoon uitzetten en je site de juiste toestanden laten zien.

Maar helaas is dat toch niet zo simpel.
Want wat als je gebruiker na 100mS (heel kort dus), nog steeds op die knop zit te drukken ?
Ga je dan meteen nog een keer 100mS dat relais aansturen ?
Dan krijg je een hoop gerammel van je relais, of hij blijft gewoon aan.
Daarom moet je ook nog iets bedenken waardoor de gebruiker eerst de knop los moet laten, voor 'ie 'm nog een keer kan indrukken.

Geloof me of niet; hoe je dat doet leer je ook uit dezelfde blink without delay methode, wanneer je die werkelijk begrepen hebt.

Dit is een op het oog heel simpel projectje, maar ondertussen niet echt een walk through voor een beginner.
Maar toch erg leuk en leerzaam (of leerzaam en daarom leuk).
Ik wens je veel succes met het project, en hoop dat je hier laat zien hoe je vordert.
Ook al is HTML niet niet echt mijn metier, ik denk graag met je mee.
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

johnvanvliet

Dank u wel MAS3,

Ik heb het al zitten bestuderen, maar doorgrond het nog niet helemaal. Al had ik al wel het idee dat ik hier naar moest kijken.

De gebruiker ben ik gelukkig gewoon zelf en het is de bedoeling dat ik de knop op mijn display indruk, dat de tekst op die knop verandert in UIT en dat de status aangeeft dat die aan is, na een tijd (in mijn voorbeeld 100 ms) zou die knop automatisch uit moeten gaan (alsof de knop opnieuw ingedrukt wordt) en de tekst op de knop weer naar AAN gaat en de status naar UIT (in de sketch heb ik 2 relais die ik aan kan sturen met 2 knoppen)

Ik kom er op terug wanneer ik de blinkwithoutdelay door heb.

Groet, John

johnvanvliet

Als ik het goed begrijp, wordt er gebruik gemaakt van de cyclus tijd?

John

MAS3

Hmm nee, niet echt.

Bij Blink without delay() gaat het er om dat je dus niet gaat staan niksen (das delay).
Je gaat gewoon door met de werkzaamheden totdat het tijd is om verder te gaan met die handeling die van de tijd afhankelijk is.
En om te weten of het tijd geworden is, moet je op de klok kijken.
Er is niemand die zegt dat je per iteratie (dat is 1 op 1 met wat jij cyclus tijd noemt) maar 1 keer op de klok mag kijken.
Dus als je ergens lang mee bezig zou zijn, kun je ook tussendoor een keer kijken.
Je moet wel in je hoofd houden dat in principe de controller 16 miljoen handelingen per seconde kan doen.
Dus ga maar eens na hoe lang (of kort) 1 iteratie duurt.
Dat kun je natuurlijk meten door aan het begin van loop op de klok te kijken en dat te communiceren, de volgende keer dat je daar weer voorbij komt kun je dan zien hoeveel tijd er verlopen is.

Het is natuurlijk niet voldoende om alleen maar op de klok te kijken, je moet natuurlijk wel onthouden waar je gebleven was.
Jij als persoon doet dat ook onbewust als je met een aantal dingen tegelijk bezig bent.
Maar omdat je je daar niet erg van bewust bent, is het wat lastiger om te bedenken wat je dan allemaal bij moet houden.

In jouw geval kan ik me voorstellen dat je onder andere moet bijhouden wanneer er op een knop gedrukt is, welke knop dat dan was, of er al relais aan staan, maar misschien ook wel wat dan daarna moet gebeuren.
En natuurlijk hoe het er met je webpage voor staat.

De voorbeelden die je krijgt bij de IDE, zijn er op gemaakt dat je ze kunt aanpassen.
Wanneer ik je ga vertellen wat je dan zou moeten aanpassen, dan zou je er wat van op kunnen steken.
Maar wanneer je zelf eens iets aanpast en dan kijkt wat er gebeurt, en gaat bedenken waarom dat dan zou gebeuren, weet ik zeker dat je er  wat van leert.
In ieder geval is dat hoe ik veel heb opgestoken tot nog toe.
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

johnvanvliet

Ben weer al wat verder, heb het een en ander in een excel sheet gezet wat er nu eigenlijk gebeurt van af het moment dat het programma start. CurrentMilles is de tijd die vanaf dat moment loopt, de currentMillis - previoudMillis is eigenlijk de delta t, en de previousMillis wordt iedere keer "gereset" op het moment dat de intervaltijd verlopen is en dus weer opnieuw kan beginnen, terwijl het programma gewoon doorloopt. Ook is in de excel sheet duidelijk te zien wanneer je de interval halveert, de knipperfrequentie verdubbeld. Hoop dat ik de theorie goed interpreteert. Straks maar weer eens verder studeren en kijken of het in mijn programmaatje te passen  is. Vind het fijn dat u mij stuurt en ja dat veranderen en kijken wat er gebeurd doe ik liever zelf in plaats van de oplossing aanreiken. Bedankt in ieder geval!

Go Up