Sunday, 14 May 2017

FreeCAD 3D modelling

Today I came across a 3D modelling tool I had not tried before. FreeCAD.


It's for parametric modelling. That's where you can change the parameters of the shapes using formulae in addition to graphically manipulating primitive shapes. This is different to the tools I have used in the past, like Blender, where you create all shapes from polygon faces, usually triangles or quads.

Each type of tool has it's advantages but for engineering modelling, which I'm doing more of at the moment for 3D printing, the parametric tools look to be very well suited.


So far all I have used FreeCAD for was to convert STP or STEP files in to STL files which I could then import in the Blender.

FreeCAD worked very well for the short time I used it. At some point I might have a go at making models in FreeCAD.

==

NodeMCU 3D models
I used FreeCAD to convert some STEP files that I downloaded from GrabCAD.

NodeMCU v0.9

I want these to help size models of cases to fit NodeMCU's in to.
Although I only have NodeMCUs in the version 1.0 style, I took the opportunity to convert a version 0.9 model as well.

NodeMCU v1.0

Downloads:
NodeMCU version 1.0 thanks to Francisco Castells available from GrabCAD in STEP format
NodeMCU version 0.9 thanks to henrik available from GrabCAD in STEP format
NodeMCU version 1.0 in STL format converted from the above by myself
NodeMCU version 0.9 in STL format converted from the above by myself
NodeMCUs both versions 1.0 and 0.9 in Blend format imported and adjusted by myself
Licence for the above (non-commercial use only)

==

Friday, 12 May 2017

Courtyard

Shelley has turned a shady neglected corner in to a lovely courtyard.


All in a day, including a trip in Fender to collect the gravel.






It needed some chairs and a table that would not sink in to the gravel.





I made these from some old scaffold boards that Shelley had recently been given.




I also added a planter from some of the off cuts.


Driveway alarm

Over a couple of days Shelley and I fitted the driveway alarm beams and the NodeMCU based transmitter.


I wanted something like a baby monitor for the cars. If anyone approaches or tries to remove a car, we get notified. Most alarm systems are expensive and tend to use GSM signals to send notifications to mobile phones. We don't have any mobile coverage at home so I wanted something that uses WiFi and the Internet. I could not find anything off the shelf, hence why I've built this.


I'm using Pushover to send push notifications to an app running on our phones. I also have a receiver for use in the house. That's still on a breadboard while I design a housing for it.



The design is fairly simple. If the normally closed switch, on the alarm sensor, is open the NodeMCU sends a push notification to mobile phones and sends network messages to any receivers on the network. There's handshaking at startup to notify all the receivers so they can monitor for tampering.


To protect the driveway I've opted for IR beams. I bought a pair of 100m range beams from ebay that accept a big range of input voltages. Anywhere between about 11Volts and 24Volts. I had a handy 12V adapter. I'm using an OKI-78SR voltage regulator. The OKI-78SR-5/1.5-W36-C I selected accepts any input voltage between 7V and 36V and drops it down to 5V which I then connect to the Vin on the NodeMCU. That way the one 12V adapter powers both the IR beams and the NodeMCU.




Both ends need power so we had to dig a trench across the drive and lay a cable. I used exterior mains cable to reduce the voltage loss. I only need two wires because my code deals with detecting tampering.


As the power is low voltage we only dug a shallow trench. One cat deep by one cat wide :-)


It was hard going as confirmed by my mattock!


I did manage to straighten it.


The wooden shuttering in the photo's is to protect the cables from the bites of horses.



The beams need to be aligned for them to work. It was easy when I tried it in the study but it was a bit fiddly in the driveway.


There's supposed to be a way to do it with a built in periscope type device but I could not work out how to use that so I did it by eye. There's a level light that gets brighter as the beams get near to alignment. You can use a voltmeter to get a more accurate setup but it works well enough without going to that degree.







I soldered the NodeMCU to a small piece of stripboard. 13x15 holes. With hindsight I should have aligned the NodeMCU to one side and used jumper wires for the LED. That would have made the voltage regulator fit better. Despite that, my layout does fit in the housing of the beam receiver, so it's OK as it is.

I used some hot glue to hold the fly leads securely under the nodeMCU. I connected the 12V socket outside the IR beam housing to minimise the wires inside. That gave me just enough space for my NodeMCU board.


All connected up, that's it.


Now every time anyone crosses the beams we get notified.

==

Bill of materials
Trigger end:
- NodeMCU (US$3.50 from China, £8.50 from the UK)
- LED (optional, about £1 for lots)
- Stripboard (£1.50 for a bit larger than needed)
- IR beam alarm (£26 from ebay)
- Cable to connect between the beam ends (£30 for 50m from ebay)
- 5V voltage regulator OKI-78SR-5/1.5-W36-C (£3 from RS Components)


Receiver end (optional):
- NodeMCU (US$3.50 from China, £8.50 from the UK)
- Red LED
- Green LED
- Passive buzzer module (£3 from the UK or less from China)


==

Download:
Alarm trigger and receiver code (zip, Arduino C)

==

Sunday, 7 May 2017

ESP8266 network broadcast

I've written a short sketch to show some of the calculations used for networking and broadcasts. This is for the NodeMCU using the Arduino IDE

I did this because I was looking for examples of networking and came across so many examples of incorrect assumptions and unnecessarily complicated code especially related to broadcast messages. It was difficult to isolate the correct information from the incorrect.

A big area of confusion is over broadcasts and multicast. These are two DIFFERENT things. Nearly always what people will want to use is BROADCAST.

Broadcasts are sent as normal packets but with the broadcast address as the destination. All clients receive broadcast packets that have been sent on their subnet. Broadcast packets are not forwarded by routers so they are just for the local network.
https://en.wikipedia.org/wiki/Unicast
https://en.wikipedia.org/wiki/Broadcasting_(networking)
https://en.wikipedia.org/wiki/Multicast

I see lots of assumptions about subnets. Most people's home networks are class C so simply changing the last octet to 255 makes it the broadcast address. That works for a class C subnet but is wrong for most other subnets.

Subnets can be any number of bits not just the common and simplified 8 bit class A, 16 bit class B or 24 bit class C.
https://en.wikipedia.org/wiki/Subnetwork

The network port is usually understood. Although any integer up to 65535 can be used, it is best to stay between 1024 and 65535. You can only read packets that are sent to the port being listened to.
It is probably best to pick a port not commonly used. There are list of registered ports usage.
https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

The following shows the calculation to get the broadcast address for any subnet and how to send broadcast packets.


#include "ESP8266WiFi.h"
#include "WiFiUdp.h"

// The port can be any integer between 1024 and 65535
const unsigned int NET_PORT = 58266;
// This uses the ESP8266 UDP class
WiFiUDP Udp;
// The network packet payload
char NetMsg_Something[] = "YourMessage";

// Let everyone else on the network know this device is present
void BroadcastPresence(){
  // Calculate this network broadcast address
  IPAddress broadcastIP = ~WiFi.subnetMask() | WiFi.gatewayIP();
  // A broadcast packet goes to every host on the subnet.
  // It is a NORMAL packet but sent to a specific address.
  Udp.beginPacket(broadcastIP, NET_PORT);
  Udp.write(NetMsg_Something);
  Udp.endPacket();
}



The example sketch that you can download from here requires two NodeMCU's running the same code so they can broadcast to each other.



Sending broadcast packets should be simple but there is some doubt if all WiFi Access Points forward network broadcast packets.
The broadcast packets worked on my network but if I find a network where they don't, it would be fairly easy to create a loop to send a unicast packet to all the possible IP addresses on any given subnet.

All that is needed is the first or last address on the network and the number of usable hosts. Those calculations are easy.


// This shows the very simple maths required to calculate some
// useful network information
void NetworkAddressCalculations(){
  // Calculate this network broadcast address
  IPAddress broadcastIP = ~WiFi.subnetMask() | WiFi.gatewayIP();
  Serial.println("Subnet broadcast address: " + broadcastIP.toString());
  // Calculate the network address
  IPAddress networkIP = WiFi.subnetMask() & WiFi.gatewayIP();
  Serial.println("Network address: " + networkIP.toString());
  // The number of usable host addresses might be usefull
  unsigned long numberOfAddresses = NumberOfHosts(WiFi.subnetMask());
  Serial.print("Number of host addresses: ");
  Serial.println(numberOfAddresses);
}

// Returns the number of usable hosts in a subnet
// The network address and the broadcast address are not usable by hosts
unsigned long NumberOfHosts(IPAddress subnet){
  subnet = ~subnet;
  return subnet[3] + (subnet[2] * 256) + (subnet[1] * 65536) + (subnet[0] * 16777216) -1;
}




The first address in a subnet is called the network address. The last address is always the broadcast address. The first and last addresses cannot be used for hosts on the network.

Although I've chosen to use the gateway address in the above examples, any address on the subnet works in the binary calculations so the following produce the exact same results for the broadcast address as we did using the gateway address in the above example:



IPAddress broadcastIP = ~WiFi.subnetMask() | WiFi.localIP();



The Internet Protocol (IP) was designed when every bit of processing power was precious and binary bit level calculations were and still are, quick to perform. Using the binary OR (|) in the above line of code and the binary AND (&) operator in the following line, the broadcast or network IP address result is the same regardless of which host IP address from within the subnet is used for the calculation.

In the following example using the local host IP produces the same network address as using the gateway IP did in the longer code sample above:


IPAddress networkIP = WiFi.subnetMask() & WiFi.localIP();



If you do create code that loops round all possible IP addresses be careful. A class B or worse a class A network has a lot of potential end points! Up to 16 million addresses on a Class A network.
Most home networks are class C so have a maximum of 254 addresses.

==

Download:
Network Broadcast Example (zip, Arduino C)

==

Monday, 1 May 2017

Use Pushover notification with ESP8266

Pushover.net is a notification service with clients for Android, iOS and Web.


The idea is that you can send a message to the service and it pops up on everyone's mobile phone that has subscribed to your channel on that service. There are lots of these types of services with slightly varying sets of features.


I was after one with pre-built clients for both Android and iOS that was simple to use and uncluttered with features that I would be unlikely to use. It also had to be free or low cost for home use.


I wanted it for sending messages from an ESP8266 used for a driveway alarm.


Up to 7500 messages the Pushover.net service is free to send messages, each person just has to pay a small one off fee for the client.


Creating an account and setting up the app and distribution group and a few other bits needs no explanation. I also took a moment to create a suitable icon. The thing that took all of the time was finding out how to send messages to Pushover.net from the ESP8266.

I found a few examples but none of them worked for me. There were some libraries specifically for Pushover however most were either overly complicated or poorly documented. Some of the sample code was very useful and I'd like to thank everyone who has posted other work on this subject. It all helped.

I eventually found the problem and then worked out a solution. The issue was that the Pushover service required the messages to be encrypted when sending to groups. The documentation, for using secure messages from the ESP8266, is a bit lacking.




#include "ESP8266WiFi.h"

// Push notifications
const String NOTIFICATION_APP =  "yourappkeyxxxxxxxxxxxxxxxxxxxx";
const String NOTIFICATION_USER = "youruserorgroupkeyyyyyyyyyyyyy";  // This can be a group or user

// Notification server
void PushNotification(String message) {
  // Pushover requires encrypted messages when sending to groups or anyone other
  // than the owner of the app
  WiFiClientSecure https;
  // Form the string
  String parameters = "token=" + NOTIFICATION_APP + "&user=" + NOTIFICATION_USER + "&message=" + message;
  int length = parameters.length();
  if (https.connect("api.pushover.net", 443)) {
    Serial.println("Start posting notification: " + parameters);
    https.println("POST /1/messages.json HTTP/1.1");
    https.println("Host: api.pushover.net");
    https.println("Connection: close\r\nContent-Type: application/x-www-form-urlencoded");
    https.print("Content-Length: ");
    https.print(length);
    https.println("\r\n");
    https.print(parameters);
    // ==
    // Reply from the server:
    while(https.connected()) {
      while(https.available()) {
        char ch = https.read();
        Serial.write(ch);
      }
    }
    // ==
    https.stop();
    Serial.println("Finished posting notification.");
  }
}



The above code worked for me. It needs some improvements to avoid the wait time for Pushover to respond but shows the basic principles.


I could then easily get the messages to appear on my Android phone and Shelley's iPad.

==

Download:
Code extract to use HTTPS with Pushover.net (zip)

==

Better Technique:
The above code will pause for a considerable amount of time if it cannot connect to Pushover or has to wait for the reply. It is easier to demonstrate using the above sample but is not how my code will look in the finished solution.

The reply from the server is probably only useful for debugging so the whole while loop for the reply can just be removed.

The following sample is a better way to handle the connection without holding up the code.




#include "ESP8266WiFi.h"

// Push notifications
const String NOTIFICATION_APP =  "yourappkeyxxxxxxxxxxxxxxxxxxxx";
const String NOTIFICATION_USER = "youruserorgroupkeyyyyyyyyyyyyy";  // This can be a group or user

const String MSG_ALARMTRIGGERED = "TEST ALARM TRIGGERED!";

WiFiClientSecure https;
bool isSendPush = false;
String pushParameters;

void loop() {
  TestTrigger();
  UpdatePushServer();
}

void TestTrigger(){
  if (isSendPush == false && digitalRead(TRIG_PIN) == HIGH)
  {
      StartPushNotification(MSG_ALARMTRIGGERED);
  }
}


void StartPushNotification(String message) {
  // Form the string
  pushParameters = "token=" + NOTIFICATION_APP + "&user=" + NOTIFICATION_USER + "&message=" + message;
  isSendPush = true;
  https.connect("api.pushover.net", 443);
  //Serial.println("Connect to push server");
}

// Keep track of the push server connection status without holding 
// up the code execution
void UpdatePushServer(){
    if(isSendPush == true && https.connected()) {
      int length = pushParameters.length();
      //Serial.println("Posting push notification: " + pushParameters);
      https.println("POST /1/messages.json HTTP/1.1");
      https.println("Host: api.pushover.net");
      https.println("Connection: close\r\nContent-Type: application/x-www-form-urlencoded");
      https.print("Content-Length: ");
      https.print(length);
      https.println("\r\n");
      https.print(pushParameters);

      https.stop();
      isSendPush = false;
      //Serial.println("Finished posting notification.");
    }
}



In this sample, the initial connect method is stand alone.
Then during each loop the update method checks to see if the server has connected. Only once it is connected does it send the message and stop.

==

Sunday, 30 April 2017

Tips for using Visual Studio Code with a NodeMCU

I am now working on the code for my project. There are a few things to know to be able to use the Ardino libraries for a NodeMCU with Visual Studio Code as the IDE.

Here are the things I needed to know:

Serial Monitor

You need to open the serial monitor BEFORE uploading the sketch to the device.


Go to the View Command Palette (F1) menu and select:
Arduino: Open Serial Monitor

If the serial monitor is not already open, any initial serial output will not be displayed.


Once open, set the COM port and the speed. I always use 115,200 baud.

If the serial monitor is already open, the implementation of the Arduino Visual Studio Code extension that I am using, temporarily disables the serial monitor for the upload and then pops it in to view and connects immediately after uploading the sketch. This is very handy behaviour.

Keep an eye out for the monitor being closed due to errors! It just needs to be re-opened.

Uploading Sketches

This has the same behaviour as the Arduion IDE. It compiles and uploads as one function.

Go to the View Command Palette (F1) menu and select:
Arduino: Upload (Ctrl+Alt+U)


This displays the OUTPUT window for the Arduino.
When complete, if the serial monitor is already open, it will re-connect the monitor and display the serial monitor window, usually.
Where I have had errors I have found the monitor does not automatically re-open!

==

I'll add to the above as I learn more.

==