Wifi farm gate controller

Hi there.
I am hoping to control a linear actuator via wifi to open and close a farm gate. I have made my own linear actuator using a motor from a cordless drill and a worm drive.
The gate is beyond the reach of my wifi network so it will be an access point which hopefully my phone will automatically connect to as I approach the gate. I then open a browser and control the gate via a web interface.

I intend to use an ESP8266-12 as the processor which will read the state of two limit switches and operate two relays via 8050 transistors. One relay is a spdt to connect power to operate the dc motor and the other is DPDT to change direction of rotation of the motor.

I intend to supply power via a 12v gel battery and use a solar panel to maintain charge. I will probably use an existing solar charge controller for this as I already have one.

I often make glaringly obvious mistakes:unamused: and so I would appreciate anyone casting an eye over the schematic and commenting or suggesting changes.

Here’s some code for the controller.

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <Hash.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

#define USE_SERIAL Serial

static const char ssid[] = "front_gate";
static const char password[] = "";
MDNSResponder mdns;

static void writeRelay(bool);

ESP8266WiFiMulti WiFiMulti;

ESP8266WebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(81);

static const char PROGMEM INDEX_HTML[] = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0">
<title>Front Gate Controller</title>
<style>
"body { background-color: #74A5EE; font-family: Arial, Helvetica, Sans-Serif; Color: #FF6F00; }"
"h1 {text-align:center; Color: #FF6F00;}"
p {text-align:center;}
</style>
<script>
var websock;
function start() {
  websock = new WebSocket('ws://' + window.location.hostname + ':81/');
  websock.onopen = function(evt) { console.log('websock open'); };
  websock.onclose = function(evt) { console.log('websock close'); };
  websock.onerror = function(evt) { console.log(evt); };
  websock.onmessage = function(evt) {
    console.log(evt);
    var e = document.getElementById('ledstatus');
    if (evt.data === 'gateOpen') {
      e.style.color = 'red';
    }
    else if (evt.data === 'gateClose') {
      e.style.color = 'green';
    }
    else {
      console.log('unknown event');
    }
  };
}
function buttonclick(e) {
  websock.send(e.id);
}
</script>
</head>
<body onload="javascript:start();">
<table cellpadding="10%" cellspacing="10%" align="center" bgcolor="#74A5EE" width="100%" style="text-align: center; ">
<tr>
<td><span align="centre"><h1>Front Gate Controller</h1></span></td>
</tr>
<tr>
<td><div class="centre" id="ledstatus"><h1>Gate</h1></div></td>
</tr>
<tr>
<td><div class="centre"><button id="gateOpen"  type="button" onclick="buttonclick(this);"><h1>-OPEN-</h1></button></div></td>
</tr>
<tr>
<td><centre><button id="gateClose" type="button" onclick="buttonclick(this);"><h1>-CLOSE-</h1></button></centre></td>
</tr>
</table>
</body>
</html>
)rawliteral";


const int relay = 4;//gate open/close relay pin
const int powerOn = 5;//power to motor relay pin
const int closedLimitSwitch = 14;// limit switch for closed position
const int OpenLimitSwitch = 12;//Limit switch for open position
bool gateStatus;// Current gate status

// Commands sent through Web Socket
const char RELAYON[] = "gateOpen";
const char RELAYOFF[] = "gateClose";

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
  USE_SERIAL.printf("webSocketEvent(%d, %d, ...)\r\n", num, type);
  switch (type) {
  case WStype_DISCONNECTED:
    USE_SERIAL.printf("[%u] Disconnected!\r\n", num);
    break;
  case WStype_CONNECTED:
  {
               IPAddress ip = webSocket.remoteIP(num);
               USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload);
               // Send the current LED status
               if (gateStatus) {
                 webSocket.sendTXT(num, RELAYON, strlen(RELAYON));
               }
               else {
                 webSocket.sendTXT(num, RELAYOFF, strlen(RELAYOFF));
               }
  }
    break;
  case WStype_TEXT:
    USE_SERIAL.printf("[%u] get Text: %s\r\n", num, payload);

    if (strcmp(RELAYON, (const char *)payload) == 0) {
      writeRelay(true);
    }
    else if (strcmp(RELAYOFF, (const char *)payload) == 0) {
      writeRelay(false);
    }
    else {
      USE_SERIAL.println("Unknown command");
    }
    // send data to all connected clients
    webSocket.broadcastTXT(payload, length);
    break;
  case WStype_BIN:
    USE_SERIAL.printf("[%u] get binary length: %u\r\n", num, length);
    hexdump(payload, length);

    // echo data back to browser
    webSocket.sendBIN(num, payload, length);
    break;
  default:
    USE_SERIAL.printf("Invalid WStype [%d]\r\n", type);
    break;
  }
}

void handleRoot()
{
  server.send_P(200, "text/html", INDEX_HTML);
}

void handleNotFound()
{
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

static void writeRelay(bool relayOn)
{
  gateStatus = relayOn;
  if (relayOn) {
	  if (digitalRead(openLimitSwitch)==1){
		  digitalWrita(powerOn, 1);
    digitalWrite(relay, 1);
	  }
	  else {
	  digitalWrite(powerOn, 0);
    digitalWrite(relay, 0);
  }
  }
  else {
	  if (digitalRead(closedLimitSwitch)==1){
		 digitalWrite(powerOn, 1);
		 digitalWrite(relay, 0);
	  }
	  else {
		  digitalWrite(powerOn, 0);
		  digitalWrite(relay, 0);
	  }
  }
}

void setup()
{
  pinMode(relay, OUTPUT);
  writeRelay(false);
  pinMode(powerOn, OUTPUT);
  digitalWrite(powerOn, LOW);
  pinMode(closedLimitSwitch, INPUT_PULLUP);
  pinMode(openLimitSwitch, INPUT_PULLUP);


  USE_SERIAL.begin(115200);

  //Serial.setDebugOutput(true);

  USE_SERIAL.println();
  USE_SERIAL.println();
  USE_SERIAL.println();

  for (uint8_t t = 4; t > 0; t--) {
    USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\r\n", t);
    USE_SERIAL.flush();
    delay(1000);
  }

//  WiFiMulti.addAP(ssid, password);
//
//  while (WiFiMulti.run() != WL_CONNECTED) {
//    Serial.print(".");
//    delay(100);
//  }

  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  USE_SERIAL.print("AP IP address: ");
  USE_SERIAL.println(myIP);

  USE_SERIAL.println("");
  USE_SERIAL.print("Connected to ");
  USE_SERIAL.println(ssid);
  USE_SERIAL.print("IP address: ");
  USE_SERIAL.println(WiFi.localIP());

  if (mdns.begin("espWebSock", WiFi.localIP())) {
    USE_SERIAL.println("MDNS responder started");
    mdns.addService("http", "tcp", 80);
    mdns.addService("ws", "tcp", 81);
  }
  else {
    USE_SERIAL.println("MDNS.begin failed");
  }
  USE_SERIAL.print("Connect to http://espWebSock.local or http://");
  USE_SERIAL.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);

  server.begin();

  webSocket.begin();
  webSocket.onEvent(webSocketEvent);
}

void loop()
{
  webSocket.loop();
  server.handleClient();
}

Just a thought… instead of using an ESP, what about a $10.00 Pi Zero-W and install a “local Blynk server” on it. Turn the Zero-W into a hot-spot and use the Blynk App to control the gate. You can even add a button (home screen App) to your smart phone home screen and not even open the App to control the gate. Have it send data back to your smart phone with the charge left in your battery.

Just a quick search on Blynk and I found this post, https://community.blynk.cc/t/setup-pi-zero-w-as-ultra-portable-server-and-ap-tutorial/12411 , You can search Blynk Community for more post, Blynk has a very good community to help you set it up…

You could probably simplify the relay portion of this by using one of these high current motor drivers (with the note you may need to add a bigger electrolytic capacitor to the input stage if your motor wants more than 1 a or so) for around $5

The limit switches being in software is a bit dangerous. I prefer the limit switches to be in series with the motor so if the processor fails and the motor hits the limit switch the power shuts off to the motor independent of the processor. If you keep the relays, in series with the relay coil that provides power is also an option (although there is still the risk of the relay contact sticking in this case). There is the complication that the limit switches need to be arranged so that if one is tripped the motor can still move the other way though. As well on the software side you may want to consider security if you haven’t already. Is it OK if just anyone that connects can open the gate? It may be, in which case no security is fine but if not then you need to figure some method of authentication (which often gets forgotten til too late :slight_smile: ). Assuming this is outside somewhere, you may also need to consider temperature. Most electronic devices stop functioning (unless they are special wide temp range devices) somewhere a fair bit below 0 and you may need to consider that if you have cold winters wherever this will be and it needs to work in winter.

Peter

Thank you Steelgoose, great reply.
No I hadn’t thought of using a rpi but I can see your point though. I did a quick search on the rpi zero W and here in Australia I cannot seem to find one for under about $25.00 +p&p :frowning:

Since the ESP8266-12 can be configured as an access point and web server, and has up to 4M storage, can I simply install the Blynk server on the ESP? Cannot seem to find any examples of that though.

Or possibly running the Blynk server on an Android phone. That would require multiple servers though as anyone using the gate would need their phone set up as a server also?

I guess the reason I went the route that I did was because I could allow as many people as I like to access the gate, (via ip access or password) without having to download an app and configure it without internet access. Imagine a cattle truck driver from the local contractor being able to use the remote control without needing to download and configure anything other than connecting to a wifi access point and opening a web interface.

I really like the idea of a widget on the home screen though since accessing your browser and loading a bookmark while driving is not good even though it’s in the middle of a paddock.

Thank you for your ideas steelgoose, I will try to find a way of making them work for me.

Thank you vanepp for your time and thoughful input.

As luck would have it, I have a similar 43A motor driver which I could use. I hadn’t thought of that. Thanks.That eliminates both relays and will enable soft start/stop function. Awesome.

I take your point regarding the limit switches. I guess I was trying to avoid large/bulky switches required to switch full motor current. I’m not sure how to configure them in the motor power circuit if I use the above motor controller.

Security is not a big issue since the gate is almost never locked now. Probably just knowing the ip address of the web interface would be more than I need. I intend to have a manual/mechanical override anyway. This whole idea is just a convenience so you don’t have to get out to open and then shut the gate/s.

Temperatures here range from about 0c to 40c.

Great ideas here thanks vanepp.

I think this circuit will work for limit switches in an h bridge (the switches need to be NC rather than the shown NO though). With no limit switch tripped, the h bridge operates as usual, when a limit switch is tripped the diodes (which need to be able to take the motor current) block movement in the limit switch direction but allow movement the other way. That said, software failure is probably a low probability event and the software version may be just fine and a lot easier.

edit: corrected the diodes as they were wrong …

Peter

I did a quick search… it appears that the server can run on any OS that can run Java 8 https://github.com/blynkkk/blynk-server#blynk-server

You could setup a web interface using Node-Red and operate it form both the Blynk App and Node-Red web UI…

Thanks again vanepp, that looks simple enough. A great solution. I have some 1N5404 or 1N5400 here so hopefully they should work.

I have used a current sensor in another project to sense a stalled motor. Might be overkill but would catch a limit switch failure.

Thanks very much for this.

Than you for your great info and link steelgoose.

I assume you are referring to a rpi here as the ESP doesn’t have the 30M RAM required to run the server.

I like this idea a lot. Where can I get $10 zero-w’s?

Really appreciate your input. Thanks again.

About 20 minutes down the road from where I live. :relaxed:

Australia

Global



https://shop.pimoroni.com/collections/raspberry-pi-zero

You haven’t confused Australia with Austria have you? :grinning:
These all come out at over $30 by the time they are shipped to the southern hemisphere.

Edit; I have found an outlet here for $26.00 but I hate paying so much when I see others getting them so much cheaper.

Whoops, wasn’t wearing my glasses… :hushed: I thought it was strange that Australia was in with Germany and Switzerland… :grin: oversight…

You could use any RPi, doesn’t need to be Zero…

You could buy me airplane tickets to “Australia” for two and I will bring you a couple “free!”…

UPDATE:
Here @moose4621 check this out… https://twitter.com/RasPiTV/status/836854904681607168/photo/1

Great link, thanks steelgoose. The rpi’s are fantastic devices.
I have a rpi3B on my sound system/tv running osmc and kodi for my entertainment system. I love it.

Being a long time linux user I am already quite comfortable with the OS and before I set it up as a entertainment system, I often used it as a headless machine to run 3d printer tasks or cnc GRBL server. I must get another one to replace it.

The zero-w will probably become easier to get at a reasonable price as manufacturing catches up with demand.

An rpi on the gate controller would be great. I could connect a camera and take an image of the registration of every vehicle/person who went through. Overkill again as I don’t have a problem with theft out here.

Thanks again for your reply.

The RPi Zero is not very fast; it is a miniaturized version of the original RPi. It is also limited on USB ports; I use a Micro USB Ethernet with 3 Port Hub https://www.amazon.com/gp/product/B00L32UUJK/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1 for programming. The Zero-W has a little PCB antenna on the side… not sure of the range. They have their place, if you need a small lightweight board. It takes a special camera ribbon for the smaller connector. The camera works great on it but programs run a little slow. I am going to use one in a RC spy critter and mount the camera in the eye…

The RPi Zero sold for $5.00 US. The Zero-W came out shortly after… and you are right… stores could not keep them on the shelves, they sold out fast. Sense you are not restricted to space or LiPo batteries I really think an old Pi2 or Pi3 would be better and maybe install a dipole antenna on top of the box for better range.

Does this mean that I have to tell my wife we are not going to Australia now… :cry:

Just down the road… http://www.microcenter.com/product/475267/zero_wireless_development_board

I am jealous. I have nothing within driving distance. Everything is mail order. :cry:

Have you tried or heard anything about the orange pi products? They look like rpi alternatives.

It looks like the zero is dead! Adafruit no longer lists it as an active product only the new zero-w, which is (as was the zero for most of its life), out of stock although I managed to snag two on the rare times they were in stock. I guess they found that $5 wasn’t a supportable price point, too bad …
(edit) spoke too soon, the Canadian distributor appears to still have zeros (although limited to 1 per customer) at $5, perhaps only adafruit has dropped them.

Peter

1 Like

In another application, we used an electric car door lock as an alternative to a linear actuator. Connected to a regular arduino motor shield. For us that was fine.

There is the Orange Pi, Nano Pi, Banana Pi, and the of course you have other alternatives like the $19.00 1GB Pine A64… Everybody and their dog are making single board computers. I would search the reviews… check Amazon and YouTube reviews…

I don’t think it is dead… they just sell out very fast… and of course the Zero-W is a little more desirable. MicroCenter uses them as a calling card… You can buy it online but you have to pick it up at the store waiting for you at will-call (they don’t ship online). Make sure you save up your mike money… MicroCenter is a candy store for DIYers… After you walk through the store you usually go home with more then just a $5.00 Zero… I know, I have experience…

Of course, they don’t even cost me $5.00… I order it online and my wife goes right past MicroCnter on her way home form work and she will pick it up and pay for it… MicroCenter is a little overwhelming, I rather have my wife pick them up for me…

I also live right in the middle of the American Amazon, Amazon has a bunch of distribution warehouses just across the river at Northern Kentucky-Cincinnati Airport (CVG). They bought 90 acres next to CVG for their international distribution center that connects to the DHL hub… Sometimes I get Amazon orders in one day, including Sunday…

It’s great how many common items around the average workshop can be re purposed for something entirely different.