rest of articles
This commit is contained in:
parent
46fee0d0e1
commit
10e888649b
12
posts/2014-04-07.01/article.m4
Normal file
12
posts/2014-04-07.01/article.m4
Normal file
@ -0,0 +1,12 @@
|
||||
define(`TITLE', `Another (better) MBus-Master, Part 6')
|
||||
define(`DATE', `2014-04-07')
|
||||
define(`CONTENT', `
|
||||
Finally, over current protection has been added.
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/04/main.pdf"><img src="http://a385e-5.de/wp-content/uploads/2014/04/main-300x211.png" alt="main" width="300" height="211" class="alignnone size-medium wp-image-447" /></a>
|
||||
|
||||
The over current protection is separated in a sensing part and a shutdown part. The comparator IC6B gets a threshold voltage using the potentiometer R18 and a signal voltage through the low pass filter of R19 and C3 (the values are not yet fine tuned). R21 and D7 are used to limit the output signal of the comparator, which is 35V power to a logic level. Through an inverter it goes to an interrupt line of the controller. An interrupt service routine in the controller firmware controls the transistor Q3 and pull down the positive input of the OP IC3A, which is part of the current source to shutdown the bus current.
|
||||
|
||||
A receiver shutdown transistor (Q4) has been added. During tests with a dedicated poewr supply serious cross talk from the sender path in to the receiver path for a bus current of about 150mA has been discovered. This has not been investigated enough, just the receiver path has been shutdown during a send cycle. This is certainly only the second best solution, but it was a quick one.
|
||||
|
||||
')
|
25
posts/2014-05-11.01/article.m4
Normal file
25
posts/2014-05-11.01/article.m4
Normal file
@ -0,0 +1,25 @@
|
||||
define(`TITLE', `Network-attached MBus-Master')
|
||||
define(`DATE', `2014-05-11')
|
||||
define(`CONTENT', `
|
||||
This is hopefully the final post concerning MBus-masters ... I replaced the Arduino Micro Pro in the "A better MBus-Master" design by a Teensy 3.1 and attached a WIZnet Ethernet module. Also, I put in a dedicated power supply providing 3.3V, 32V and 34V, based on two MC34063.
|
||||
|
||||
3.3V for the Teensy and the WIZnet.
|
||||
|
||||
34V to power the devices of the analog part of the design.
|
||||
|
||||
32V for the bus. This give all the devices in the analog port 2V headroom.
|
||||
|
||||
The "receive path disable MOSFET" has been removed again.
|
||||
|
||||
Bringing the Teensy to reliable work was a bit hard, but this follows in another post.
|
||||
|
||||
And this it is and it works:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/05/IMG_2028.jpg"><img src="http://a385e-5.de/wp-content/uploads/2014/05/IMG_2028-300x225.jpg" alt="IMG_2028" width="300" height="225" class="alignnone size-medium wp-image-453" /></a>
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/05/IMG_2030.jpg"><img src="http://a385e-5.de/wp-content/uploads/2014/05/IMG_2030-300x225.jpg" alt="IMG_2030" width="300" height="225" class="alignnone size-medium wp-image-454" /></a>
|
||||
|
||||
And finally it is in "production":
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/05/Foto-e1399978198908.jpg"><img src="http://a385e-5.de/wp-content/uploads/2014/05/Foto-e1399978198908-225x300.jpg" alt="Foto" width="225" height="300" class="alignnone size-medium wp-image-462" /></a>
|
||||
')
|
8
posts/2014-05-11.02/article.m4
Normal file
8
posts/2014-05-11.02/article.m4
Normal file
@ -0,0 +1,8 @@
|
||||
define(`TITLE', `4 Channel MBus-connected Thermometer, Part 3')
|
||||
define(`DATE', `2014-05-11')
|
||||
define(`CONTENT', `
|
||||
This thermometer is working too now and is attached to my local MBus:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/05/IMG_2032.jpg"><img src="http://a385e-5.de/wp-content/uploads/2014/05/IMG_2032-300x225.jpg" alt="IMG_2032" width="300" height="225" class="alignnone size-medium wp-image-455" /></a>
|
||||
|
||||
')
|
31
posts/2014-08-04.01/article.m4
Normal file
31
posts/2014-08-04.01/article.m4
Normal file
@ -0,0 +1,31 @@
|
||||
define(`TITLE', `Review of network-attached M-Bus master, design version 6')
|
||||
define(`DATE', `2014-08-04')
|
||||
define(`CONTENT', `
|
||||
I got some questions about the design version 6, which I describe <a href="http://a385e-5.de/?p=445" title="http://a385e-5.de/?p=445">here</a> and the modifications I applied to turn it into a network-attached M-Bus master, which I describe <a href="http://a385e-5.de/?p=456" title="here">here</a>.
|
||||
|
||||
Here is a kind of a personal review of that design, especially considering the modifications:
|
||||
|
||||
|
||||
<ul>
|
||||
<li>I replaced the Arduino Pro Micro by an Teensy 3.1 connected to a WIZNet module.</li>
|
||||
<li>I introduced a power supply with three voltages: 34V, 32V and 3.3V.</li>
|
||||
<li>3.3V obviously for the MCU, the ethernet module and the 74HC04, 34V for the main analog part, it just replaced the VCC in the schematics.</li>
|
||||
<li>Than I removed the four diodes D1-4 and connected 32V directly to the top terminal of R6.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
While in the design version 6 I had a very clear voltage shift at pin 1 of IC1A of about 100mV for the received logic levels at the bus, this signal was very noisy in the later design. Before replacing the diodes D1-4 by a separate supply voltage, it was nearly unusable and I was not able to communicate reliably using the device.
|
||||
|
||||
After introducing the separate 32V supply voltage the signal got better, but still not as good as in design version 6. However, I was able to communicate again.
|
||||
|
||||
Nevertheless I ran into another problem: the SNR was going worse for very small and very large bus currents. So, I added a 10k resistor parallel to R7 to drain a minimum bus current of about 3mA and I had to limit the maximum bus current to about 70mA. This is equal to about 70 slave devies. In my setup this is no problem, I use the device just for fun in the basement, in other setups, where actually 250 slaves should be handled, it is a problem.
|
||||
|
||||
I think the major cause for the noise is the stronger, higher clocked, MCU and the WIZnet, which impact noise into the ground lines. (Unfortunately, the Arduino flash is not large enough for my firmware after adding the ethernet code.) And moreover my "breadboard production approach" is certainly a problem. A well layouted PCB with large supply planes leads hopefully to much better results and some more bypass capacitors and ferrit beads would help too.
|
||||
|
||||
May be increasing the value of R6 should also be considered. It would increase the voltage shift at the output of a difference amplifier after the S/H device (pin 1 of IC1A).
|
||||
|
||||
All in all, considering both the <a href="http://a385e-5.de/?p=445" title="http://a385e-5.de/?p=445">design version 6</a> and the <a href="http://a385e-5.de/?p=456" title="here">network-attached M-Bus master</a>, it becomes clear that it is possible to build a network-attached M-Bus master using the concept.
|
||||
|
||||
|
||||
|
||||
')
|
21
posts/2014-10-04.01/article.m4
Normal file
21
posts/2014-10-04.01/article.m4
Normal file
@ -0,0 +1,21 @@
|
||||
define(`TITLE', `2-Wire Lightsensor with MBus-interface (bus-powered)')
|
||||
define(`DATE', `2014-10-04')
|
||||
define(`CONTENT', `
|
||||
Today it was a 2-wire (so: bus-powered) light sensor with MBus-interface:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/10/IMG_2378.jpg"><img src="http://a385e-5.de/wp-content/uploads/2014/10/IMG_2378-300x225.jpg" alt="IMG_2378" width="300" height="225" class="alignnone size-medium wp-image-497" /></a>
|
||||
|
||||
Here, it is already mounted on the sill outside the window with a piece of double-faced adhesive tape, enclosed in the package of an Apple Magic Mouse.
|
||||
|
||||
Note the piece in the lower-right corner (not the 10k resistor, next to it). This is finally the light sensor. It is regular BC177 transistor in metal case with the cap removed with a small Proxxon cutting-off machine. Works perfectly.
|
||||
|
||||
The whole thing consumes about 500uA (the jumper in the top-middle is in the power line between the bus-transceiver and the rest of the circuit, just to measure the current).
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/10/scan_006048.pdf"><img src="http://a385e-5.de/wp-content/uploads/2014/10/scan_006048-300x211.png" alt="scan_006048" width="300" height="211" class="alignnone size-medium wp-image-494" /></a>
|
||||
|
||||
BTW, this is my first MSP430 project. It is much more "low-power" than the AVRs on the Arduino boards ...
|
||||
|
||||
One note on the inhouse-wiring: The MBus-master is in the basement, the light sensor on the second floor. How to bring the MBus upstairs? Just use the already available infrastructure (Ethernet) cabling, which goes up from the patch panel in the basement into every room.
|
||||
|
||||
Here are the sources: <a href="http://a385e-5.de/wp-content/uploads/2014/10/MBusLightSensor-2014-10-05.zip">MBusLightSensor-2014-10-05</a>
|
||||
')
|
17
posts/2014-10-27.01/article.m4
Normal file
17
posts/2014-10-27.01/article.m4
Normal file
@ -0,0 +1,17 @@
|
||||
define(`TITLE', `A simple Modbus RTU to TCP gateway')
|
||||
define(`DATE', `2014-10-27')
|
||||
define(`CONTENT', `
|
||||
Meterbus is a great Thing, especially as two-wire slave (bus-powered) are possible. Unfortunately the Meterbus Transceiver TSS721A is rather expensive and not that easy to obtain.
|
||||
|
||||
So, I decided to test another fieldbus: Modbus. A Modbus Transceiver (here: LTC485) is much cheaper than the TSS721A and moreover a 1-phase powermeter with Modbus interface is about 30€, a 1-phase powermeter with Meterbus interface is about 90€.
|
||||
|
||||
I found some Arduino libraries for both Modbus RTU and Modbus TCP on the Net so I started with a simple Modbus master talking to a 1-phase powermeter:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/10/IMG_1045.jpg"><img src="http://a385e-5.de/wp-content/uploads/2014/10/IMG_1045-300x225.jpg" alt="IMG_1045" width="300" height="225" class="alignnone size-medium wp-image-506" /></a>
|
||||
|
||||
Communication works:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/2014/10/SCR04.png"><img src="http://a385e-5.de/wp-content/uploads/2014/10/SCR04-300x243.png" alt="SCR04" width="300" height="243" class="alignnone size-medium wp-image-507" /></a>
|
||||
|
||||
(Blue and yellow are the Modbus lines, purple is TX at the microcontroller, green is RT at the microcontroller.)
|
||||
')
|
27
posts/2014-12-11.01/article.m4
Normal file
27
posts/2014-12-11.01/article.m4
Normal file
@ -0,0 +1,27 @@
|
||||
define(`TITLE', `Measuring the speed of a salad spinner')
|
||||
define(`DATE', `2014-12-11')
|
||||
define(`CONTENT', `
|
||||
Have you ever been wondering with how many revolutions your salad spinner is running? Here is the measuring:
|
||||
|
||||
First, attach a hall-probe to the salad spinner bowl, the exact position needs to be found by experiment:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_2597.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2597-300x225.jpg" alt="IMG_2597" width="300" height="225" class="alignnone size-medium wp-image-507" /></a>
|
||||
|
||||
Second, attach two small but strong magnets at the spinner, one on each side, to let it run weighty:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2014/12/img_2600.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2600-300x225.jpg" alt="IMG_2600" width="300" height="225" class="alignnone size-medium wp-image-508" /></a>
|
||||
|
||||
Third, connect the probe to a power-supply, an oscilloscope and a frequency-counter:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_2599.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2599-300x225.jpg" alt="IMG_2599" width="300" height="225" class="alignnone size-medium wp-image-509" /></a>
|
||||
|
||||
The oscilloscope is required to find the right position of the probe, the counter is required for the actually measurement.
|
||||
|
||||
And then: turn the spinner:
|
||||
|
||||
[youtube https://www.youtube.com/watch?v=ezTvoh3vguI&w=560&h=315]
|
||||
|
||||
Here, in this clip, we measured about 43Hz. In another test it was even 52Hz.
|
||||
|
||||
Since we have two magnets, we had 21.5 rps and in the other test 26 rps. These are 1290 rpm and 1560 rpm. That's fast.
|
||||
')
|
38
posts/2014-12-15.01/article.m4
Normal file
38
posts/2014-12-15.01/article.m4
Normal file
@ -0,0 +1,38 @@
|
||||
define(`TITLE', `Very simple metal detector')
|
||||
define(`DATE', `2014-12-15')
|
||||
define(`CONTENT', `
|
||||
The design of the <a href="http://a385e-5.de/?s=theremin">Theremin</a> let my to the idea, that varying the value of the inductivity by approaching some metal should also detune one of two oscillators.
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/20141215123534365a.pdf"><img class="alignnone size-medium wp-image-515" src="http://a385e-5.de/wp-content/uploads/20141215123534365a-300x212.png" alt="20141215123534365a" width="500" /></a>
|
||||
|
||||
Here, I reuse the design of the oscillator and the mixer from my <a href="http://a385e-5.de/?s=theremin">Theremin</a> and fed the mixed signal into a low pass filter, calculated with Analog's excellent <a href="http://www.analog.com/designtools/en/filterwizard/" target="_blank">Filter Wizard</a>.
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2014/12/img_2629.jpg"><img class="alignnone size-medium wp-image-532" src="http://a385e-5.de/wp-content/uploads/IMG_2629-300x225.jpg" alt="IMG_2629" width="500" /></a>
|
||||
|
||||
This was btw the first deployment of my new Rigol power supply:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_2615-e1418650869673.jpg"><img class="alignnone size-medium wp-image-521" src="http://a385e-5.de/wp-content/uploads/IMG_2615-e1418650869673-300x225.jpg" alt="IMG_2615" width="300" height="225" /></a>
|
||||
|
||||
The both identical 30V-Max-channels, put in tracking mode, can easily be used as a symmetric power supply, as it is required for the mixer and the filter.
|
||||
|
||||
The reference frequency is provided using a generator:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2014/12/img_2616.jpg"><img class="alignnone size-medium wp-image-549" src="http://a385e-5.de/wp-content/uploads/IMG_2616-300x225.jpg" alt="IMG_2616" width="300" height="225" /></a>
|
||||
|
||||
|
||||
|
||||
This is the full measurement setup:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2014/12/img_2630.jpg"><img class="alignnone size-medium wp-image-533" src="http://a385e-5.de/wp-content/uploads/IMG_2630-300x225.jpg" alt="IMG_2630" width="300" height="225" /></a>
|
||||
|
||||
I use one oscilloscope to show the varying (yellow) and the reference (blue) frequency, here in the tuned state:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2014/12/tuned.png"><img class="alignnone size-medium wp-image-518" src="http://a385e-5.de/wp-content/uploads/tuned-300x219.png" alt="tuned" width="300" height="219" /></a>
|
||||
|
||||
When detuning the test oscillator by approaching some metal to the coil, there varying frequency starts wandering on the screen:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/detuned.png"><img class="alignnone size-medium wp-image-519" src="http://a385e-5.de/wp-content/uploads/detuned-300x219.png" alt="detuned" width="300" height="219" /></a>
|
||||
And here are the results:
|
||||
|
||||
[gallery columns="2" ids="546,545,544,525,543,528,541,540,535,534"]]]>
|
||||
')
|
34
posts/2015-01-01.01/article.m4
Normal file
34
posts/2015-01-01.01/article.m4
Normal file
@ -0,0 +1,34 @@
|
||||
define(`TITLE', `A small Royer Induction Heater')
|
||||
define(`DATE', `2015-01-01')
|
||||
define(`CONTENT', `
|
||||
It actually works!
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/01/img_2723.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2723-300x225.jpg" alt="IMG_2723" width="300" height="225" class="alignnone size-medium wp-image-565" /></a>
|
||||
|
||||
Of course it works, several people built it before and published photos and videos. But now I did it on my own: a rather small induction heater.
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_2719.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2719-300x300.jpg" alt="IMG_2719" width="300" height="300" class="alignnone size-medium wp-image-566" /></a>
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/01/scan_006379.png"><img src="http://a385e-5.de/wp-content/uploads/scan_006379-300x287.png" alt="scan_006379" width="300" height="287" class="alignnone size-medium wp-image-571" /></a>
|
||||
|
||||
In the first photo I ran it with only 12V and at about 2.5A, but this was enough to bring a small nail to red heat.
|
||||
|
||||
Some waveforms:
|
||||
|
||||
|
||||
At the gate of one of the MOSFETs:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/gate.png"><img src="http://a385e-5.de/wp-content/uploads/gate-300x244.png" alt="gate" width="300" height="244" class="alignnone size-medium wp-image-567" /></a>
|
||||
|
||||
|
||||
At the drain of one of the MOSFETs:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/01/drain.png"><img src="http://a385e-5.de/wp-content/uploads/drain-300x244.png" alt="drain" width="300" height="244" class="alignnone size-medium wp-image-568" /></a>
|
||||
|
||||
|
||||
And finally across the capacitor:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/capacitor.png"><img src="http://a385e-5.de/wp-content/uploads/capacitor-300x244.png" alt="capacitor" width="300" height="244" class="alignnone size-medium wp-image-569" /></a>
|
||||
|
||||
|
||||
')
|
86
posts/2015-06-05.02/article.m4
Normal file
86
posts/2015-06-05.02/article.m4
Normal file
@ -0,0 +1,86 @@
|
||||
define(`TITLE', `WiFi Powermeter')
|
||||
define(`DATE', `2015-06-05')
|
||||
define(`CONTENT', `
|
||||
The WiFi Powermeter is a electric power meter which sends its measurement results every minute using the MQTT protocol via WiFi to an MQTT broker in the local network.
|
||||
|
||||
Here is the open test setup:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/06/img_3151.jpg"><img class="alignnone size-medium wp-image-593" src="http://a385e-5.de/wp-content/uploads/IMG_3151-300x225.jpg" alt="IMG_3151" width="300" height="225" /></a>
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
This is how it looks in its box:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_3217.jpg"><img class="alignnone size-medium wp-image-594" src="http://a385e-5.de/wp-content/uploads/IMG_3217-225x300.jpg" alt="IMG_3217" width="225" height="300" /></a>
|
||||
|
||||
I used it to measure the power consumption of the fridge in the basement or of the PC of my son and so on.
|
||||
|
||||
On the MQTT broker there is one subscriber who transfers all the measurements into a MongoDB, where it now waits for further analysis.
|
||||
|
||||
The hardware is rather simple: an Arduino Mega (since it has more than one serial interface), an Arduino WiFi shield and on top a RS485 adaptor for the Modbus communication.
|
||||
|
||||
For the software I'm using the Modbus library from <a href="https://code.google.com/p/simple-modbus/">https://code.google.com/p/simple-modbus/</a>. Unfortunately, it disappeared right there, don't know why. Seems, that I have to be really careful with the files. The MQTT library I'm using is from <a href="http://knolleary.net/arduino-client-for-mqtt/">http://knolleary.net/arduino-client-for-mqtt/</a>.
|
||||
|
||||
With the couple of the WiFi library and the MQTT library I ran into two problems.
|
||||
|
||||
First, it was not possible to establish an MQTT connection at all. Strange, since via Ethernet it wasn't a problem at all. I found, supported by Google that that the WiFi library and the shield handles a <tt>stop()</tt> on a fresh client socket somewhat strange: The socket can not be open or will be closed immediately after opening. Since at least in my case I always give a fresh <tt>WiFiClient</tt> into the <tt>PubSubClient</tt> I removed the <tt>connected()</tt> call from the top of the <tt>connect</tt> method in <tt>PubSubClient.cpp</tt>.
|
||||
|
||||
Second, I ran into the problem that messages I published via PubSubClient using an Arduino Mega and an Arduino Wifi Shield which are large than about 80 octets did not appear at the broker. I found by googling that it is not possible to send more than 90 octets using the Wifi Shield and the related library at once: http://mssystems.emscom.net/helpdesk/knowledgebase.php?article=51
|
||||
And that exactly what I experienced too: I increased the buffer size one by one and at 90 octets it stopped and the WiFi library lost the connection.
|
||||
|
||||
Using this patch, which I applied against release 1.9.1 everything works fine now:
|
||||
|
||||
[code language="cpp"]
|
||||
42,43c42
|
||||
< // if (!connected()) {
|
||||
< if (true) {
|
||||
---
|
||||
> if (!connected()) {
|
||||
217d215
|
||||
< // Serial.print("pub len: "); Serial.println(length-5);
|
||||
219,220d216
|
||||
< } else {
|
||||
< // Serial.println("connection lost");
|
||||
290,308c286
|
||||
<
|
||||
< // Serial.print("write len: "); Serial.println(length+1+llen);
|
||||
< // size_t olen = length + 1 + llen;
|
||||
< // rc = _client->write(buf+(4-llen),length+1+llen);
|
||||
<
|
||||
< const size_t SEND_AT_ONCE = 64;
|
||||
< size_t remains = length + 1 + llen;
|
||||
< // Serial.print("write len: "); Serial.println(remains);
|
||||
< const uint8_t *writebuf = buf + (4 - llen);
|
||||
< bool result = true;
|
||||
< while ((remains > 0) && result) {
|
||||
< size_t actuallySendChars = (remains > SEND_AT_ONCE) ? SEND_AT_ONCE : remains;
|
||||
< // Serial.print("tbs: "); Serial.println(actuallySendChars);
|
||||
< size_t sentChars = _client->write(writebuf, actuallySendChars);
|
||||
< result = sentChars == actuallySendChars;
|
||||
< remains -= sentChars;
|
||||
< writebuf += sentChars;
|
||||
< }
|
||||
<
|
||||
---
|
||||
> rc = _client->write(buf+(4-llen),length+1+llen);
|
||||
311,312c289
|
||||
< // return (rc == 1+llen+length);
|
||||
< return result;
|
||||
---
|
||||
> return (rc == 1+llen+length);
|
||||
357,362c334
|
||||
< //Serial.print("rc: "); Serial.println(rc);
|
||||
< if (!rc) {
|
||||
< //Serial.println("would stop");
|
||||
< _client->stop();
|
||||
< // while (true);
|
||||
< }
|
||||
---
|
||||
> if (!rc) _client->stop();
|
||||
[/code]
|
||||
|
||||
|
||||
Sources for the firmware are here: <a href="http://a385e-5.de/wp-content/uploads/WiModbusGateway.zip">WiModbusGateway</a>
|
||||
')
|
174
posts/2015-06-05.03/article.m4
Normal file
174
posts/2015-06-05.03/article.m4
Normal file
@ -0,0 +1,174 @@
|
||||
define(`TITLE', `Revisiting the MeterBus master')
|
||||
define(`DATE', `2015-06-05')
|
||||
define(`CONTENT', `
|
||||
I was already talking about the network attached MeterBus master <a href="http://a385e-5.de/?p=445" target="_blank">here</a> and <a href="http://a385e-5.de/?p=475" target="_blank">here</a> early. By now, a cronjob on my MacMini in the basement was querying the device every minute to collect measurement results from the attached meters (water, gas, electricity, out door temperature).
|
||||
|
||||
Now, I changed and improved the software slightly:
|
||||
|
||||
First, I enabled the watchdog timer, since it occasionally happened that the device became unresponsive. In this case now the watchdog timer is triggered to reset the beast.
|
||||
|
||||
Second, I modified the upstream communication. Now the master publishes the results of configured meters using the MQTT protocol.
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/06/img_3167.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_3167-300x225.jpg" alt="IMG_3167" width="300" height="225" class="alignnone size-medium wp-image-605" /></a>
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
Doing this, I ran into another problem with the MQTT library from <a href="http://knolleary.net/arduino-client-for-mqtt/" target="_blank">http://knolleary.net/arduino-client-for-mqtt/</a>. I had to increase the maximum packet size to 1024 bytes since some of the meters sent about 250 bytes, which I represent in a hex string in the MQTT payload. But as soon as the packet was higher the 256 bytes, only the first 256 bytes had been sent to the broker. Tracking this down to the <tt>write</tt> method in the MQTT library I found a <tt>uint8_t</tt> which a <tt>uint16_t</tt> should be:
|
||||
|
||||
[code language="cpp"]
|
||||
boolean PubSubClient::write(uint8_t header, uint8_t* buf,
|
||||
uint16_t length) {
|
||||
uint8_t lenBuf[4];
|
||||
uint8_t llen = 0;
|
||||
uint8_t digit;
|
||||
uint8_t pos = 0;
|
||||
uint8_t rc;
|
||||
uint8_t len = length;
|
||||
[/code]
|
||||
|
||||
Using <tt>uint16_t</tt> for the variable <tt>len</tt> immediately fixed this problem.
|
||||
|
||||
Aha, and enabling the watchdog on the Teensy was also not that easy. Finally, I came to this solution:
|
||||
|
||||
[code language="cpp"]
|
||||
extern "C" {
|
||||
void startup_early_hook( ) __attribute__ ((weak));
|
||||
void startup_early_hook() {
|
||||
// enable watchdog
|
||||
WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
|
||||
WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
|
||||
|
||||
// one minute
|
||||
WDOG_TOVALL = 0xea60;
|
||||
WDOG_TOVALH = 0;
|
||||
WDOG_PRESC = 0;
|
||||
|
||||
WDOG_STCTRLH = WDOG_STCTRLH_WDOGEN |
|
||||
WDOG_STCTRLH_ALLOWUPDATE |
|
||||
WDOG_STCTRLH_STOPEN |
|
||||
WDOG_STCTRLH_WAITEN;
|
||||
}
|
||||
} // extern "C"
|
||||
[/code]
|
||||
|
||||
It this require the enable the watchdog in the <tt>startup_early_hook</tt> since the Cortex accepts it only the first 256 clock cycles.
|
||||
Next, the <tt>extern "C"</tt> is important, otherwise the link does not find the overwrite of the function, since it is compile with a C++ file.
|
||||
|
||||
The clock for the watchdog is taken from the LPO of the CPU, which is running at 1kHz. Thus, a timeout value of 0xea60 equals 60000 let to a watchdog timeout of one minute. Reading the K20 reference manual, which I found on the Teensy homepage, was really helpful here.
|
||||
|
||||
|
||||
|
||||
Today, all the measurements from a couple of meters find their way via MQTT and a small serverside script into the MongoDB for further analysis.
|
||||
|
||||
[code language="javascript"]
|
||||
{
|
||||
"data":{
|
||||
"telegram":"68 38 38 68 08 51 72 10 01 00 13 2E 19 24 02
|
||||
9C 00 00 00 8C 10 04 12 06 00 00 8C 11 04 12
|
||||
06 00 00 02 FD C9 FF 01 E2 00 02 FD DB FF 01
|
||||
00 00 02 AC FF 01 00 00 82 40 AC FF 01 00 00
|
||||
09 16 ",
|
||||
"uptime":52815
|
||||
},
|
||||
"metadata":{
|
||||
"device":"MeterbusHub",
|
||||
"token":5,
|
||||
"name":"dryer"
|
||||
}
|
||||
}
|
||||
{
|
||||
"data":{
|
||||
"telegram":"68 61 61 68 08 21 72 00 00 00 00 00 00 01 00
|
||||
AA 00 00 00 01 24 03 01 25 0A 01 26 10 02 27
|
||||
01 00 05 67 28 14 B3 3D 05 67 D2 45 E3 BA 05
|
||||
67 9F B5 A7 41 05 67 79 13 E0 41 0F D0 27 00
|
||||
00 AA 08 00 00 05 00 00 00 00 00 00 00 01 00
|
||||
00 00 A2 C3 7F 3F A5 BA 7F 3F 85 A7 7F 3F E7
|
||||
F9 7F 3F CD CC CC 3D E8 03 00 00 8B 16 ",
|
||||
"uptime":52822
|
||||
},
|
||||
"metadata":{
|
||||
"device":"MeterbusHub",
|
||||
"token":1,
|
||||
"name":"thermom."
|
||||
}
|
||||
}
|
||||
{
|
||||
"data":{
|
||||
"telegram":"68 38 38 68 08 52 72 99 51 00 13 2E 19 21 02
|
||||
86 00 00 00 8C 10 04 06 09 00 00 8C 11 04 00
|
||||
09 00 00 02 FD C9 FF 01 E3 00 02 FD DB FF 01
|
||||
00 00 02 AC FF 01 00 00 82 40 AC FF 01 00 00
|
||||
B3 16 ",
|
||||
"uptime":52840
|
||||
},
|
||||
"metadata":{
|
||||
"device":"MeterbusHub",
|
||||
"token":6,
|
||||
"name":"laundry"
|
||||
}
|
||||
}
|
||||
{
|
||||
"data":{
|
||||
"telegram":"68 92 92 68 08 50 72 81 14 01 11 2E 19 16 02
|
||||
A2 00 00 00 8C 10 04 82 62 85 00 8C 11 04 82
|
||||
62 85 00 8C 20 04 00 00 00 00 8C 21 04 00 00
|
||||
00 00 02 FD C9 FF 01 DD 00 02 FD DB FF 01 08
|
||||
00 02 AC FF 01 0F 00 82 40 AC FF 01 00 00 02
|
||||
FD C9 FF 02 E2 00 02 FD DB FF 02 0C 00 02 AC
|
||||
FF 02 16 00 82 40 AC FF 02 F7 FF 02 FD C9 FF
|
||||
03 E9 00 02 FD DB FF 03 09 00 02 AC FF 03 11
|
||||
00 82 40 AC FF 03 FA FF 02 FF 68 00 00 02 AC
|
||||
FF 00 36 00 82 40 AC FF 00 F1 FF 01 FF 13 00
|
||||
D2 16 ",
|
||||
"uptime":52867
|
||||
},
|
||||
"metadata":{
|
||||
"device":"MeterbusHub",
|
||||
"token":4,
|
||||
"name":"electricity"
|
||||
}
|
||||
}
|
||||
{
|
||||
"data":{
|
||||
"telegram":"68 46 46 68 08 30 72 45 71 43 00 24 23 25 07
|
||||
4B 00 00 00 0C 13 83 50 43 00 8C 10 13 00 00
|
||||
00 00 0B 3B 00 00 00 0B 26 69 58 01 02 5A B6
|
||||
00 04 6D 30 0D E5 16 4C 13 96 41 33 00 CC 10
|
||||
13 00 00 00 00 42 6C DF 1C 42 EC 7E FF 1C 01
|
||||
16 ",
|
||||
"uptime":53047
|
||||
},
|
||||
"metadata":{
|
||||
"device":"MeterbusHub",
|
||||
"token":2,
|
||||
"name":"water"
|
||||
}
|
||||
}
|
||||
{
|
||||
"data":{
|
||||
"telegram":"68 56 56 68 08 40 72 43 60 52 00 77 04 14 03
|
||||
56 10 00 00 0C 78 76 03 01 10 0D 7C 08 44 49
|
||||
20 2E 74 73 75 63 0A 30 30 30 30 30 30 30 30
|
||||
30 30 04 6D 23 0D E5 16 02 7C 09 65 6D 69 74
|
||||
20 2E 74 61 62 A9 09 04 13 F5 A9 04 00 04 93
|
||||
7F 4E 01 00 00 44 13 FC A5 04 00 0F 01 00 1F
|
||||
1C 16 ",
|
||||
"uptime":53049
|
||||
},
|
||||
"metadata":{
|
||||
"device":"MeterbusHub",
|
||||
"token":3,
|
||||
"name":"gas"
|
||||
}
|
||||
}
|
||||
|
||||
[/code]
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/06/img_3168.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_3168-225x300.jpg" alt="IMG_3168" width="225" height="300" class="alignnone size-medium wp-image-604" /></a>
|
||||
|
||||
|
||||
Sources for the firmware are here: <a href="http://a385e-5.de/wp-content/uploads/NetMeterBusMaster2.zip">NetMeterBusMaster2</a>
|
||||
')
|
92
posts/2015-06-05.04/article.m4
Normal file
92
posts/2015-06-05.04/article.m4
Normal file
@ -0,0 +1,92 @@
|
||||
define(`TITLE', `RelayBox')
|
||||
define(`DATE', `2015-06-05')
|
||||
define(`CONTENT', `
|
||||
Have you ever been in the situation that you are on the way to the office, or even more worse into holiday, and you can not remember certainly enough whether you switched off the oven or the tumble dryer. I was so often in that situation that I decided <i>to make</i> this:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/06/img_3234.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_3234-300x225.jpg" alt="IMG_3234" width="250" class="alignnone size-medium wp-image-621" /></a>
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/06/img_3235.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_3235-300x225.jpg" alt="IMG_3235" width="250" class="alignnone size-medium wp-image-622" /></a>
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
|
||||
On the first photo you see three high current switches (and on the right hand side two MBus power meters), on the second photo is the control stuff. From the bottom to the top there is a Meanwell power supply with 24V DC output for the switches and next to it a 5V SMPS for the Arduino. In the middle left is a card with eight opto coupler and an insulating DC-DC-converter for the feedback from the switches and on the right hand side an Arduino Mega with an Ethernet Shield. On top left just a row of screw terminal and on the left hand side a 8 port relay board from SainSmart. It is so cheap on ebay (only about 11€) you can not make it on you own - the parts would be more expensive.
|
||||
|
||||
For eight ports 16 input and 16 output pins on the Arduino are required: eight in and eight out for feedback and relays, eight in and eight out for push buttons and signaling LEDs (they are not on the photo).
|
||||
|
||||
This thing is controlled using the MQTT protocol too. A small Python coded webapp also siting on the broker serves as UI:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/06/img_3258.png"><img src="http://a385e-5.de/wp-content/uploads/IMG_3258-169x300.png" alt="IMG_3258" width="169" height="300" class="alignnone size-medium wp-image-624" /></a>
|
||||
|
||||
("Waschküche" is laundry room, "Küche" is kitchen and "Herd" is oven.)
|
||||
|
||||
The thing publishes every second the status of the switches via MQTT:
|
||||
|
||||
[code language="javascript"]
|
||||
{
|
||||
"data":{
|
||||
"uptime":75407,
|
||||
"switchStates":[
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":0,
|
||||
"state":1,
|
||||
"feedbackState":1
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":1,
|
||||
"state":1,
|
||||
"feedbackState":1
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":2,
|
||||
"state":1,
|
||||
"feedbackState":1
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":3,
|
||||
"state":0,
|
||||
"feedbackState":0
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":4,
|
||||
"state":0,
|
||||
"feedbackState":0
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":5,
|
||||
"state":0,
|
||||
"feedbackState":0
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":6,
|
||||
"state":0,
|
||||
"feedbackState":0
|
||||
},
|
||||
{
|
||||
"stateConflict":0,
|
||||
"index":7,
|
||||
"state":0,
|
||||
"feedbackState":0
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata":{
|
||||
"device":"RelayBox"
|
||||
}
|
||||
}
|
||||
[/code]
|
||||
|
||||
|
||||
The sources for the webapp are here: <a href="http://a385e-5.de/wp-content/uploads/RelayBoxWebApp.zip">RelayBoxWebApp</a>
|
||||
|
||||
The sources for the firmware are here: <a href="http://a385e-5.de/wp-content/uploads/RelayBox.zip">RelayBox</a>
|
||||
')
|
47
posts/2015-06-17.01/article.m4
Normal file
47
posts/2015-06-17.01/article.m4
Normal file
@ -0,0 +1,47 @@
|
||||
define(`TITLE', `A fully digital controlled SMPS for up to 100V, 1.5KW')
|
||||
define(`DATE', `2015-06-17')
|
||||
define(`CONTENT', `
|
||||
The whole beast:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2941-e1426606766331.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2941-e1426606766331-300x225.jpg" alt="IMG_2941" width="300" height="225" class="alignnone size-medium wp-image-580" /></a>
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
|
||||
Transformer, 230V to 90V, 1.5KW, 11kg, 12€ on ebay
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2944-e1426606813947.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2944-e1426606813947-225x300.jpg" alt="IMG_2944" width="225" height="300" class="alignnone size-medium wp-image-583" /></a>
|
||||
|
||||
|
||||
Transformer Start Relay
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2945-e1426606881884.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2945-e1426606881884-225x300.jpg" alt="IMG_2945" width="225" height="300" class="alignnone size-medium wp-image-576" /></a>
|
||||
|
||||
|
||||
Rectifier
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2946-e1426606909895.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2946-e1426606909895-225x300.jpg" alt="IMG_2946" width="225" height="300" class="alignnone size-medium wp-image-577" /></a>
|
||||
|
||||
|
||||
Filter capacitors (4x5100uF), with discharging resistor (10kOhm)
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2948-e1426606963504.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2948-e1426606963504-300x225.jpg" alt="IMG_2948" width="300" height="225" class="alignnone size-medium wp-image-579" /></a>
|
||||
|
||||
|
||||
Power stage with switch, diode (in one package, 300A, 1000V), inductor (about 140uH) and capacitors (2x2000uF)
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2943-e1426607017130.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2943-e1426607017130-225x300.jpg" alt="IMG_2943" width="225" height="300" class="alignnone size-medium wp-image-582" /></a>
|
||||
|
||||
|
||||
Controller, with MSP430, opto-coupler and push-pull-stage for driving the power switch with PWM signal from MCU, voltage-divider and op-amp for feedback voltage, display and some pushbuttons
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2942-e1426607103291.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2942-e1426607103291-300x225.jpg" alt="IMG_2942" width="300" height="225" class="alignnone size-medium wp-image-581" /></a>
|
||||
|
||||
|
||||
Load for testing
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/03/img_2947-e1426607276880.jpg"><img src="http://a385e-5.de/wp-content/uploads/IMG_2947-e1426607276880-225x300.jpg" alt="IMG_2947" width="225" height="300" class="alignnone size-medium wp-image-578" /></a>
|
||||
|
||||
')
|
178
posts/2015-09-14.01/article.m4
Normal file
178
posts/2015-09-14.01/article.m4
Normal file
@ -0,0 +1,178 @@
|
||||
define(`TITLE', `First ESP8266 Project: WiFi Power Switch')
|
||||
define(`DATE', `2015-09-14')
|
||||
define(`CONTENT', `
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_3826-e1442696191894.jpg" rel="attachment wp-att-693"><img src="http://a385e-5.de/wp-content/uploads/IMG_3826-e1442696191894-768x1024.jpg" alt="IMG_3826" width="474" height="632" class="alignnone size-large wp-image-693" /></a>
|
||||
|
||||
The ESP8266 boards (ESP-01, cmp. <a href="http://www.esp8266.com/wiki/doku.php?id=esp8266-module-family#esp-01"> http://www.esp8266.com/wiki/doku.php?id=esp8266-module-family#esp-01 </a>
|
||||
) were lying on my desk for already some time. I never took the time to install the SDK on my Mac. Now I came around nodemcu (<a href="http://www.nodemcu.com/index_en.html"> http://www.nodemcu.com/index_en.html</a>) and it is exactly what I was looking for since a while: <a href="http://www.lua.org/">Lua</a> on a microcontroller. The idea behind is simple: When you are coding on a PC (or a Mac) and you have a rather small problem, a rather simple task to perform, you (or at least: I) would tend to use a scripting language. On a PC my first choice would be Python, other people prefer Perl or even Lua. On a microcontroller I also was faced those simple tasks (like toggling one bit based on an MQTT message) but never had a scripting language available. But here it is.
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
No need to install an SDK on the PC, just an upload tool like <a href="https://github.com/kmpm/nodemcu-uploader">nodemcu-uploader.py</a> or <a href="http://esp8266.ru/esplorer/">esplorer</a> is required. First the nodemcu firmware needs to be installed on the ESP8266 board. I found a very good intro <a href="http://www.whatimade.today/loading-the-nodemcu-firmware-on-the-esp8266-windows-guide/">here</a>.
|
||||
|
||||
My Lua script for this project running on the microcontroller consists of two files: ''init.lua'' and ''mqtt.lua''.
|
||||
Coding Lua for nodemcu isn't really intuitive, at least not when you come from Arduinos or so. You can't simple write a ''setup'' method and do all the initialization within and a ''loop'' method to be continuously run. Doing it this way would either drive you into the chip's watchdog and would consume any available CPU any and leave nothing for the WiFi and TCP/IP stack. You've to work with timers and callback functions. I found two really good articles <a href="https://primalcortex.wordpress.com/2014/12/30/esp8266-nodemcu-and-lua-language-and-some-arduino-issues/">here</a> and <a href="https://primalcortex.wordpress.com/2015/02/06/nodemcu-and-mqtt-how-to-start/">here</a>.
|
||||
|
||||
What I also had to learn the hard way is that the nodemcu does not leave much space for the script. With a handful of debug messages containing some meaningful text (as it is no problem on the Arduino or Teensy) I over and over run into out of memory messages or even worse in misbehaving code.
|
||||
|
||||
I finally came to this code:
|
||||
|
||||
<pre>
|
||||
-- init.lua
|
||||
-- Constants
|
||||
SSID = "MessWLAN"
|
||||
APPWD = "geheim"
|
||||
CMDFILE = "mqtt.lua"
|
||||
|
||||
-- Some control variables
|
||||
wifiTrys = 0
|
||||
NUMWIFITRYS = 200
|
||||
|
||||
function launch()
|
||||
print("A")
|
||||
print("B: " .. wifi.sta.getip())
|
||||
tmr.alarm(0, 5000, 0, function() dofile(CMDFILE) end )
|
||||
end
|
||||
|
||||
function checkWIFI()
|
||||
if ( wifiTrys > NUMWIFITRYS ) then
|
||||
print("C")
|
||||
else
|
||||
ipAddr = wifi.sta.getip()
|
||||
if ( ( ipAddr ~= nil ) and ( ipAddr ~= "0.0.0.0" ) )then
|
||||
tmr.alarm( 1 , 500 , 0 , launch )
|
||||
else
|
||||
tmr.alarm( 0 , 2500 , 0 , checkWIFI)
|
||||
print("D: " .. wifiTrys)
|
||||
wifiTrys = wifiTrys + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("E")
|
||||
|
||||
ipAddr = wifi.sta.getip()
|
||||
if ( ( ipAddr == nil ) or ( ipAddr == "0.0.0.0" ) ) then
|
||||
print("F")
|
||||
wifi.setmode( wifi.STATION )
|
||||
wifi.sta.config( SSID , APPWD)
|
||||
print("G")
|
||||
tmr.alarm( 0 , 2500 , 0 , checkWIFI )
|
||||
else
|
||||
launch()
|
||||
end
|
||||
</pre>
|
||||
|
||||
|
||||
<pre>
|
||||
BROKER = "172.16.2.15"
|
||||
BRPORT = 1883
|
||||
BRUSER = ""
|
||||
BRPWD = ""
|
||||
CLIENTID = "ESP8266-" .. node.chipid()
|
||||
|
||||
SWITCH_PIN = 3
|
||||
|
||||
SWITCH_ID = 1
|
||||
|
||||
topics = {"IoT/Watchdog", "IoT/Switch" .. SWITCH_ID}
|
||||
TOPIC_WATCHDOG = 1
|
||||
TOPIC_SWITCH = 2
|
||||
|
||||
pub_sem = 0
|
||||
current_topic = 1
|
||||
topicsub_delay = 50
|
||||
id2 = 0
|
||||
|
||||
switch_state = false
|
||||
old_switch_state = true
|
||||
|
||||
|
||||
function alarm()
|
||||
node.restart()
|
||||
end
|
||||
|
||||
|
||||
gpio.mode(SWITCH_PIN, gpio.OUTPUT)
|
||||
gpio.write(SWITCH_PIN, gpio.LOW)
|
||||
|
||||
m = mqtt.Client( CLIENTID, 120, BRUSER, BRPWD)
|
||||
tmr.alarm(4, 60000, 1, alarm)
|
||||
m:connect( BROKER , BRPORT, 0, function(conn)
|
||||
print("4")
|
||||
mqtt_sub()
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
function mqtt_sub()
|
||||
if table.getn(topics) < current_topic then
|
||||
run_main_prog()
|
||||
else
|
||||
m:subscribe(topics[current_topic] , 0, function(conn)
|
||||
end)
|
||||
current_topic = current_topic + 1
|
||||
tmr.alarm(5, topicsub_delay, 0, mqtt_sub )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function publish_status()
|
||||
if pub_sem == 0 then
|
||||
pub_sem = 1
|
||||
local uptime = tmr.time()
|
||||
local switch_state_pres = 0
|
||||
if (switch_state) then
|
||||
switch_state_pres = 1
|
||||
end
|
||||
local msg = "{"metadata":{"device":"WiFiSwitch" .. SWITCH_ID .. ""}, "data":{"uptime":" .. uptime .. ", "state":" .. switch_state_pres .. "}}"
|
||||
m:publish("IoT/Status/WiFiSwitch" .. SWITCH_ID, msg ,0,0, function(conn)
|
||||
print("8: " .. id2 .. ", " .. switch_state_pres)
|
||||
pub_sem = 0
|
||||
id2 = id2 +1
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function run_main_prog()
|
||||
tmr.alarm(3, 1000, 1, publish_status )
|
||||
m:on("message", function(conn, topic, data)
|
||||
print(topic .. ":" )
|
||||
if (data ~= nil ) then
|
||||
print ( data )
|
||||
if (topic == topics[TOPIC_SWITCH] and data == "switch on") then
|
||||
switch_state = true
|
||||
elseif (topic == topics[TOPIC_SWITCH] and data == "switch off") then
|
||||
switch_state = false
|
||||
elseif (topic == topics[TOPIC_SWITCH] and data == "switch toggle") then
|
||||
switch_state = not switch_state
|
||||
elseif (topic == topics[TOPIC_WATCHDOG] and data == "WauWau!") then
|
||||
print("9")
|
||||
tmr.alarm(4, 60000, 1, alarm)
|
||||
end
|
||||
|
||||
if (switch_state ~= old_switch_state) then
|
||||
old_switch_state = switch_state
|
||||
if (switch_state) then
|
||||
gpio.write(SWITCH_PIN, gpio.LOW)
|
||||
else
|
||||
gpio.write(SWITCH_PIN, gpio.HIGH)
|
||||
end
|
||||
end
|
||||
end
|
||||
end )
|
||||
end
|
||||
</pre>
|
||||
|
||||
<img src="http://a385e-5.de/wp-content/uploads/IMG_3814-1024x768.jpg" alt="IMG_3814" width="474" height="356" class="alignnone size-large wp-image-688" />
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2015/09/scan_006894_1.pdf"><img src="http://a385e5.files.wordpress.com/2015/09/scan_006894.png" alt="scan_006894" width="924" height="603" class="alignnone size-full wp-image-675" /></a>
|
||||
|
||||
|
||||
Important note: this thing runs on mains power. Don't play with it unless you know exactly what you are doing!
|
||||
')
|
120
posts/2015-10-12.01/article.m4
Normal file
120
posts/2015-10-12.01/article.m4
Normal file
@ -0,0 +1,120 @@
|
||||
define(`TITLE', `Something completely different: SNMP to MySQL')
|
||||
define(`DATE', `2015-10-12')
|
||||
define(`CONTENT', `
|
||||
I'm helping to maintain a fleet of about 50 printers in a charity distributed over about 30 locations in the city. Now, we wanted to know how much the individual printers are used to get some numbers for an effort to reduce the number of printers.
|
||||
|
||||
So, what is more self-evident then using SNMP to query the total page counter on a daily base - or better on an hourly base since the printers are switched off at this or that time and those we at least get sometimes valid data.
|
||||
|
||||
Typical monitoring tools like Cacti or Zabbix are very good in drawing nice graphs but not so good in delivering absolute numbers. So I decided to write something on my own: query some devices for some SNMP data points and store the results in a database. Which devices and which data points and which combinations? Everything in the database too.
|
||||
|
||||
I looked for a SNMP library, first in Python, then in Java - since I'm quite familiar with these languages - but everything I found was rather complicated to use. Then I looked for something in C# and found ''SnmpSharpNet''. Still not that easy to use but easier then what I found in Python or Java.
|
||||
|
||||
For that reason I started coding the little tool in C#. And what I did is working very well now. Configuration and error-handling is not perfect yet, but it is working. Enough for today.
|
||||
|
||||
BTW: I switched developing the code between Microsoft Visual Studio 2013 (on Windows) and Xamarin Studio (on the Mac) and run the tool on Linux. Works without any problem. Very nice!
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
[code language="csharp"]
|
||||
namespace Snmp2Mysql
|
||||
{
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string dbConnStr = "SERVER=localhost;" +
|
||||
"DATABASE=statsdb;" +
|
||||
"UID=statsuser;" +
|
||||
"PASSWORD=xxx;";
|
||||
DatabaseLink dbLink = new DatabaseLink(dbConnStr);
|
||||
using (DataCollector dc = dbLink.DataCollector)
|
||||
using (DeviceProvider dp = dbLink.DeviceProvider)
|
||||
{
|
||||
foreach (DeviceTuple dt in dp)
|
||||
{
|
||||
// Console.WriteLine("dt: {0}, {1}", dt.DeviceAddress, dt.Community);
|
||||
|
||||
using (SnmpGetter snmpGetter = new SnmpGetter(dt.Community, dt.DeviceAddress))
|
||||
{
|
||||
using (DeviceDataItemProvider ddip = dt.DeviceDataItemProvider)
|
||||
{
|
||||
foreach (DeviceDataItemTuple ddit in dt.DeviceDataItemProvider)
|
||||
{
|
||||
// Console.WriteLine(" ddit: {0}, {1}", ddit.Id, ddit.Oid);
|
||||
snmpGetter.AddOid(ddit.Id, ddit.Oid);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SnmpGetterResultProvider res = snmpGetter.Exec();
|
||||
foreach (SnmpGetterResult r in res)
|
||||
{
|
||||
// Console.WriteLine("{0} {1} {2} {3}: {4}", dt.Description, r.Index, r.Oid, r.Type, r.Value);
|
||||
dc.add((int)r.Index, r.Value);
|
||||
}
|
||||
}
|
||||
catch (SnmpGetterException) {
|
||||
// Console.WriteLine ("{0}, no result: {1}", dt.Description, e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[/code]
|
||||
|
||||
[code language="SQL"]
|
||||
CREATE TABLE `device_t` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`address` varchar(45) NOT NULL,
|
||||
`community` varchar(45) NOT NULL,
|
||||
`period` int(11) NOT NULL,
|
||||
`description` varchar(123) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `address_UNIQUE` (`address`)
|
||||
|
||||
CREATE TABLE `dataitem_t` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`oid` varchar(128) NOT NULL,
|
||||
`description` varchar(45) NOT NULL,
|
||||
`handling` varchar(45) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `oid_UNIQUE` (`oid`),
|
||||
UNIQUE KEY `description_UNIQUE` (`description`)
|
||||
|
||||
CREATE TABLE `devicedataitem_t` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`device` int(11) NOT NULL,
|
||||
`dataitem` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `devicedataitem_uk_idx` (`device`,`dataitem`),
|
||||
KEY `device_fk_idx` (`device`),
|
||||
KEY `dataitem_fk_idx` (`dataitem`),
|
||||
CONSTRAINT `dataitem_fk` FOREIGN KEY (`dataitem`) REFERENCES `dataitem_t` (`id`),
|
||||
CONSTRAINT `device_fk` FOREIGN KEY (`device`) REFERENCES `device_t` (`id`)
|
||||
|
||||
CREATE TABLE `collecteddata_t` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`devicedataitem` int(11) NOT NULL,
|
||||
`value` varchar(512) NOT NULL,
|
||||
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `devicedataitem_fk_idx` (`devicedataitem`),
|
||||
CONSTRAINT `devicedataitem_fk` FOREIGN KEY (`devicedataitem`) REFERENCES `devicedataitem_t` (`id`)
|
||||
[/code]
|
||||
|
||||
And here are the sources:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/Snmp2Mysql.zip">Snmp2Mysql</a>
|
||||
|
||||
I'm using GPL code from MySQL (the MySQL Connector for .NET), find it here <a href="http://dev.mysql.com/downloads/connector/net/" target="_blank">http://dev.mysql.com/downloads/connector/net/</a> and the SNMP library from <a href="http://www.snmpsharpnet.com" target="_blank">http://www.snmpsharpnet.com</a>.
|
||||
|
||||
Ah, evaluation of the data? Haven't thought about, maybe using some tricky SQL statement or an Excel pivot table. I'll come back about that.
|
||||
|
||||
')
|
19
posts/2016-03-03.01/article.m4
Normal file
19
posts/2016-03-03.01/article.m4
Normal file
@ -0,0 +1,19 @@
|
||||
define(`TITLE', `Why always SPI CS on pin 10?')
|
||||
define(`DATE', `2016-03-03')
|
||||
define(`CONTENT', `
|
||||
Thank you, Ladyada, for <a href="https://learn.adafruit.com/adafruit-2-8-tft-touch-shield-v2">this great display</a>.
|
||||
|
||||
But why is TFT CS on pin 10?
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/03/bildschirmfoto-2016-03-03-um-21-48-49.png" rel="attachment wp-att-711"><img src="http://a385e5.files.wordpress.com/2016/03/bildschirmfoto-2016-03-03-um-21-48-49.png" alt="Bildschirmfoto 2016-03-03 um 21.48.49" width="722" height="449" class="alignnone size-full wp-image-711" /></a>
|
||||
|
||||
Pin 10 is also the SPI CS for the Ethernet shield. Why not, for instance, pin 6:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/03/img_1211-e1457038834523.jpg" rel="attachment wp-att-712"><img src="http://a385e-5.de/wp-content/uploads/IMG_1211-e1457038834523-1024x768.jpg" alt="IMG_1211" width="474" height="356" class="alignnone size-large wp-image-712" /></a>
|
||||
|
||||
Carefully lift pin 9 of the level shifter and connect it using a thin wire with pin 6 of the Arduino connector.
|
||||
|
||||
And voila, both the display and the ethernet shield is working:
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/03/img_1212-e1457039094609.jpg" rel="attachment wp-att-713"><img src="http://a385e-5.de/wp-content/uploads/IMG_1212-e1457039094609-1024x768.jpg" alt="IMG_1212" width="474" height="356" class="alignnone size-large wp-image-713" /></a>
|
||||
')
|
24
posts/2016-09-09.01/article.m4
Normal file
24
posts/2016-09-09.01/article.m4
Normal file
@ -0,0 +1,24 @@
|
||||
define(`TITLE', `Integrated Thermometer and Timer')
|
||||
define(`DATE', `2016-09-09')
|
||||
define(`CONTENT', `
|
||||
To brew green tea you need water of about 75°C. To know that your water has 100°C is easy, you can see that it is boiling. For 75°C you need a thermometer. Then you also need to take care about the brewing time. It should be usually two minutes.
|
||||
|
||||
There are such integrated thermometer and timer things on Amazon, but that's not me cup of tea, I decided to build one on my own. It should run on batteries, it should be small and it should make no noise (for office use).
|
||||
|
||||
In between I was reading "Patterns for Time-Triggered Embedded Systems" from Michael Pont. And afterwards I was curious to use such a simple cooperative scheduler instead of the super-loop, as it is common in the Arduino domain.
|
||||
|
||||
I used a MSP430G2553 with 10bit-ADCs, a PT1000 sensor and two seven-segment LED displays.
|
||||
|
||||
The code is available at <a href="https://bitbucket.org/wollud1969/teathermotimer" target="_blank">https://bitbucket.org/wollud1969/teathermotimer</a>.
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/09/img_0813-e1473432862286.jpg" rel="attachment wp-att-720"><img src="http://a385e-5.de/wp-content/uploads/IMG_0813-e1473432862286-768x1024.jpg" alt="img_0813" width="474" height="632" class="alignnone size-large wp-image-720" /></a>
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/09/img_0814.jpg" rel="attachment wp-att-721"><img src="http://a385e-5.de/wp-content/uploads/IMG_0814-1024x768.jpg" alt="img_0814" width="474" height="356" class="alignnone size-large wp-image-721" /></a>
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/IMG_0815.jpg" rel="attachment wp-att-722"><img src="http://a385e-5.de/wp-content/uploads/IMG_0815-1024x768.jpg" alt="img_0815" width="474" height="356" class="alignnone size-large wp-image-722" /></a>
|
||||
|
||||
Schematics: <a href="http://a385e5.files.wordpress.com/2016/09/201609091558_0001.pdf">201609091558_0001</a>
|
||||
|
||||
Calculation for measurement: <a href="http://a385e5.files.wordpress.com/2016/09/201609091558_0002.pdf">201609091558_0002</a>
|
||||
|
||||
')
|
18
posts/2016-09-12.01/article.m4
Normal file
18
posts/2016-09-12.01/article.m4
Normal file
@ -0,0 +1,18 @@
|
||||
define(`TITLE', `Integrated Tea Timer and Thermometer, Second Edition')
|
||||
define(`DATE', `2016-09-12')
|
||||
define(`CONTENT', `
|
||||
I've two offices, so I'm requiring two of this timers.
|
||||
|
||||
The second one I built with a three-digit display and auto-power-down and start with a push-button.
|
||||
|
||||
This thing consumes in operation about 20mA, which is a real lot for so few functionality, but most of the power goes into the display. I was looking for a simple LCD on ebay, but it seems that most of the LCD 7-segment display have only one common and one pin for every single segment instead of one common per digit. These are too many pins for the 2553 and I didn't want to put an additional LCD controller on the board.
|
||||
|
||||
However, when the thing goes in LPM4, it only consumes about 0,1uA, as it is written in the datasheet. Very important to achieve this low power consumption: an input pin requires more power than an output pin put into the right level. And of course the reference generator of the ADC needs to be shutdown.
|
||||
|
||||
The sources are still available here https://bitbucket.org/wollud1969/teathermotimer, look for the branch <code>SecondEdition</code>.
|
||||
|
||||
The schematic is more or less the same, just on digit display more and a reset push-button.
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/09/img_0818-e1473677307841.jpg" rel="attachment wp-att-730"><img src="http://a385e-5.de/wp-content/uploads/IMG_0818-e1473677307841-768x1024.jpg" alt="img_0818" width="474" height="632" class="alignnone size-large wp-image-730" /></a>
|
||||
<a href="http://a385e5.files.wordpress.com/2016/09/img_0821-e1473677332189.jpg" rel="attachment wp-att-731"><img src="http://a385e-5.de/wp-content/uploads/IMG_0821-e1473677332189-1024x768.jpg" alt="img_0821" width="474" height="356" class="alignnone size-large wp-image-731" /></a>
|
||||
')
|
38
posts/2016-10-14.01/article.m4
Normal file
38
posts/2016-10-14.01/article.m4
Normal file
@ -0,0 +1,38 @@
|
||||
define(`TITLE', `Three Phase Inverter')
|
||||
define(`DATE', `2016-10-14')
|
||||
define(`CONTENT', `
|
||||
Already when I was still in school, about 30 years ago, I was curious to make an inverter using some MOSFETs. I actually was able to build a simple one phase inverter with rectangular signal shape (I used a NE555). Using this thing I drove a transformer to light a blub. However, all of these inverters I built passed by in fire.
|
||||
|
||||
Now, I tried it again, not longer using MOSFETs but IGBTs with free-wheeling diode. Moreover, I used some microcontrollers and sine values to feed a PWM to get a sine-alike signal shape. And immediately with three phases to drive an asynchronous motor.
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/img_0053.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0053.jpg?w=730" alt="img_0053" width="730" height="973" class="alignnone size-large wp-image-740" /></a>
|
||||
|
||||
The signal shaping is done with four MSP430 controllers, three as PWMs to drive the bridge and one to coordinate and control the three PWMs. The PWM controller is decoupled from the IGBT driver (IR2184) using optic couplers.
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/img_0054-e1476437702547.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0054-e1476437702547.jpg?w=730" alt="img_0054" width="730" height="548" class="alignnone size-large wp-image-741" /></a>
|
||||
|
||||
The bridge is a three phase IGBT module is a 6MB120F-060 I got for a few euros at ebay.
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/img_0055-e1476437685461.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0055-e1476437685461.jpg?w=730" alt="img_0055" width="730" height="548" class="alignnone size-large wp-image-742" /></a>
|
||||
|
||||
To avoid high voltages in my setup I got a 24V async motor, also from ebay.
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/img_0056.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0056.jpg?w=730" alt="img_0056" width="730" height="548" class="alignnone size-large wp-image-743" /></a>
|
||||
|
||||
The PWMs generate the signal from a sine table generated using Excel. Those we got this signal:
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/inverter0_2016-09-23-4.png"><img src="https://a385e5.files.wordpress.com/2016/10/inverter0_2016-09-23-4.png" alt="inverter0_2016-09-23-4" width="640" height="520" class="alignnone size-full wp-image-759" /></a>
|
||||
|
||||
The main task of the coordinator is the start the PWMs with a phase shift of 120° (digital line 1, 2 and 3):
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/2016-10-13_1.png"><img src="https://a385e5.files.wordpress.com/2016/10/2016-10-13_1.png" alt="2016-10-13_1" width="640" height="520" class="alignnone size-full wp-image-757" /></a>
|
||||
|
||||
Currently the PWMs start with random polarity. The interesting signals are the digital lines 4, 5 and 6.
|
||||
|
||||
Sometimes the motor runs:
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works.png"><img src="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works.png" alt="2016-10-13_works" width="640" height="520" class="alignnone size-full wp-image-753" /></a>
|
||||
|
||||
But sometimes not:
|
||||
<a href="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works_not.png"><img src="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works_not.png" alt="2016-10-13_works_not" width="640" height="520" class="alignnone size-full wp-image-754" /></a>
|
||||
|
||||
The firmware is available on bitbucket, for the PWM controllers <a href="https://bitbucket.org/wollud1969/inverter0.git" target="_blank">here</a> and for the coordinator <a href="https://bitbucket.org/wollud1969/inverter0ctrl.git" target="_blank">here</a>.
|
||||
|
||||
')
|
47
posts/2016-11-02.01/article.m4
Normal file
47
posts/2016-11-02.01/article.m4
Normal file
@ -0,0 +1,47 @@
|
||||
define(`TITLE', `Something really useful: 433MHz Power-Outlet Control')
|
||||
define(`DATE', `2016-11-02')
|
||||
define(`CONTENT', `
|
||||
We've lots of more or less cheap 433MHz Switchable Power-Outlets in the house, mostly for decorative lights. You get them for under 15€ in the Building Center, three at once with a remote control. Usually, you can control four switches with one remote, period. (A promising exceptions are the device from Intertechno.)
|
||||
|
||||
Now I was looking for a way to
|
||||
<ol>
|
||||
<li>Control the switches from different manufacturers with one remote.</li>
|
||||
<li>Control them from really remote - from the office or from holiday.</li>
|
||||
<li>Control them programmatically.</li>
|
||||
</ol>
|
||||
There are a couple of Arduino libraries out there which are working with this cheap 433MHz senders and receivers from China:
|
||||
|
||||
|
||||
|
||||
<img class=" size-full wp-image-775 aligncenter" src="https://a385e5.files.wordpress.com/2016/11/sender_receiver.png" alt="sender_receiver" width="406" height="386" />I tried several ones, not all a really working, but finally I stopped at <a href="https://github.com/sui77/rc-switch" target="_blank">https://github.com/sui77/rc-switch</a>, which works really good.
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
First challenge now is to get the codes out of the remotes. For this purposes the rc-switch library provides an example sketch for the Arduino. I extended it a bit and got this:
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/11/img_01012-e1478087121580.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_01012-e1478087121580.jpg?w=730" alt="img_0101" width="730" height="548" class="alignnone size-large wp-image-791" /></a>
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/11/img_0105.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_0105.jpg?w=730" alt="img_0105" width="730" height="548" class="alignnone size-large wp-image-784" /></a>
|
||||
|
||||
|
||||
Software for this thing can be found here <a href="https://gitlab.com/wolutator/433Receiver.git" target="_blank">https://gitlab.com/wolutator/433Receiver.git</a>.
|
||||
|
||||
This is how it works:
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/11/img_0111-e1478087101747.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_0111-e1478087101747.jpg?w=730" alt="img_0111" width="730" height="548" class="alignnone size-large wp-image-799" /></a>
|
||||
|
||||
|
||||
The second challenge is to send the codes out into air and let the power switches receive them. This is done with this thing:
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/11/img_0100-e1478087375824.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_0100-e1478087375824.jpg?w=730" alt="img_0100" width="730" height="548" class="alignnone size-large wp-image-803" /></a>
|
||||
|
||||
It is a Arduino Ethernet Board with a PoE-adapter and the 433MHz sender directly attached to it. I glued it under a table in the living room.
|
||||
|
||||
This thing received messages via MQTT and send them out via 433MHz.
|
||||
|
||||
The software is here https://gitlab.com/wolutator/Mqtt433Gateway.git
|
||||
|
||||
BTW: do not expect beautiful software, this has been made on Halloween evening and night when waiting for the kids to come home.
|
||||
|
||||
')
|
26
posts/2016-12-19.01/article.m4
Normal file
26
posts/2016-12-19.01/article.m4
Normal file
@ -0,0 +1,26 @@
|
||||
define(`TITLE', `Three Phase Inverter, Second Service')
|
||||
define(`DATE', `2016-12-19')
|
||||
define(`CONTENT', `
|
||||
I wrote in October about my first try to build a simple three phase inverter, see here <a href="https://a385e5.wordpress.com/2016/10/14/three-phase-inverter/" target="_blank">https://a385e5.wordpress.com/2016/10/14/three-phase-inverter/</a>. In the first try I used four MSP430 microcontroller, one for the PWM of each phase and one to coordinate the phase shift of the three phases.
|
||||
|
||||
In this experiment I put everything on one STM32 microcontroller. Here I used the DMA feature to feed data into the PWM counter and I calculated the sine values at start-up time on the microcontroller. Additionally I put in the driver for a CAN interface, however, it is not yet supported in the firmware.
|
||||
|
||||
<img class="alignnone size-full wp-image-815" src="https://a385e5.files.wordpress.com/2016/12/img_0140.jpg" alt="img_0140" width="3024" height="4032" />
|
||||
|
||||
From top to bottom you see the CAN driver, the STM32 board, opto coupler to separate logic and power part and then from right to left in the bottom half the low-side/high-side MOSFET drivers and the MOSFETs.
|
||||
|
||||
<img class="alignnone size-full wp-image-820" src="https://a385e5.files.wordpress.com/2016/12/img_0144.jpg" alt="img_0144" width="3024" height="4032" />
|
||||
|
||||
The power supply consists of a traditional transformer and (top right) the rectifier and condensers for the power part, together with the 12V regulator for the drivers and (top left) the regulators for 3.3V and 5V for the logic part.
|
||||
|
||||
<img class="alignnone size-full wp-image-825" src="https://a385e5.files.wordpress.com/2016/12/img_0146.jpg" alt="img_0146" width="4032" height="3024" />
|
||||
|
||||
The motor is the same as in the earlier experiment - I don't have too much of them. And everything is put onto one board:
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://a385e5.files.wordpress.com/2016/12/img_0143-e1482141676335.jpg"><img src="https://a385e5.files.wordpress.com/2016/12/img_0143-e1482141676335.jpg?w=730" alt="img_0143" width="730" height="548" class="alignnone size-large wp-image-830" /></a>
|
||||
|
||||
(Some space reserved for a HMI unit to be connected via CAN ...)
|
||||
')
|
11
posts/2017-07-04.01/article.m4
Normal file
11
posts/2017-07-04.01/article.m4
Normal file
@ -0,0 +1,11 @@
|
||||
define(`TITLE', `SPI Slave Select Multiplication for the Raspberry Pi')
|
||||
define(`DATE', `2017-07-04')
|
||||
define(`CONTENT', `
|
||||
|
||||
|
||||
|
||||
<img class="alignnone size-full wp-image-838" src="https://a385e5.files.wordpress.com/2017/07/rpi_ss1.png" alt="rpi_ss1" width="640" height="520" />
|
||||
|
||||
<img class="alignnone size-full wp-image-840" src="https://a385e5.files.wordpress.com/2017/07/img_0594.jpg" alt="IMG_0594" width="4032" height="3024" />
|
||||
|
||||
')
|
277
posts/2018-01-26.01/article.m4
Normal file
277
posts/2018-01-26.01/article.m4
Normal file
@ -0,0 +1,277 @@
|
||||
define(`TITLE', `Configuration-Webserver for ESP8266 Projects')
|
||||
define(`DATE', `2018-01-26')
|
||||
define(`CONTENT', `
|
||||
In my previous ESP8266 based weekend projects I always hardcoded configuration data. For the ESP8266 these are at least the WiFi credentials SSID and WPA key. Moving it into a different WiFi network requires re-flashing it. There must be a better way I thought and found that's a single line of code to run the ESP8266 as an accesspoint, which opens its own WiFi network.
|
||||
|
||||
So, I first hardcoded a web page with a form to enter configuration data, a data structure to hold it and some code to store it into the EEPROM or load it there.
|
||||
It appears that this was an error-prone process with a lot of redudancy in the code.
|
||||
|
||||
For that reason I wrote an approach with a small template-based generator script:<!--more-->
|
||||
|
||||
|
||||
|
||||
|
||||
[code language="python" title="configGen.py"]
|
||||
#!/usr/bin/python
|
||||
|
||||
from Cheetah.Template import Template
|
||||
|
||||
configItems = [
|
||||
{"label":"_", "key":"magic", "type":"I", "default": ""},
|
||||
{"label":"Wifi SSID", "key":"wifiSsid", "type":"C", "length":32, "default":"test"},
|
||||
{"label":"Wifi Key", "key":"wifiKey", "type":"C", "length":64, "default":"geheim"},
|
||||
{"label":"MQTT Broker", "key":"mqttBroker", "type":"C", "length":64, "default":"broker.hottis.de"},
|
||||
{"label":"MQTT Username", "key":"mqttUser", "type":"C", "length":32, "default":"esp1"},
|
||||
{"label":"MQTT Password", "key":"mqttPass", "type":"C", "length":32, "default":"geheim"},
|
||||
{"label":"MQTT ClientId", "key":"mqttClientId", "type":"C", "length":32, "default":"changeThis"},
|
||||
{"label":"MQTT Topic", "key":"mqttTopic", "type":"C", "length":64, "default":"IoT/espThermometer2/location/measurement"},
|
||||
{"label":"MQTT Port", "key":"mqttPort", "type":"I", "default":8883},
|
||||
{"label":"Measure Period", "key":"measurePeriod", "type":"I", "default":300}
|
||||
]
|
||||
|
||||
h_file = Template(file="configuration_h.tmpl", searchList=[{"configItems":configItems}])
|
||||
open('configuration.h','w').write(str(h_file))
|
||||
c_file = Template(file="configuration_c.tmpl", searchList=[{"configItems":configItems}])
|
||||
open('configuration.cpp','w').write(str(c_file))
|
||||
[/code]
|
||||
|
||||
|
||||
The two templates are:
|
||||
|
||||
[code language="C" title="configuration_h.tmpl"]
|
||||
typedef struct {
|
||||
#for $configItem in $configItems
|
||||
#if $configItem.type == 'C'
|
||||
char ${configItem.key}[$configItem.length];
|
||||
#else if $configItem.type == 'I'
|
||||
uint32_t $configItem.key;
|
||||
#end if
|
||||
#end for
|
||||
} tConfigBlock;
|
||||
|
||||
extern const uint32_t MAGIC;
|
||||
extern tConfigBlock configBlock;
|
||||
|
||||
void configServeIndex();
|
||||
void configServeGetConfiguration();
|
||||
void showConfiguration();
|
||||
[/code]
|
||||
|
||||
And:
|
||||
|
||||
[code language="C" title="configuration_c.tmpl"]
|
||||
#raw
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "configuration.h"
|
||||
#end raw
|
||||
|
||||
|
||||
tConfigBlock configBlock;
|
||||
const uint32_t MAGIC = 0xC0DE0001;
|
||||
extern ESP8266WebServer webServer;
|
||||
|
||||
bool configSaved = false;
|
||||
|
||||
void configServeIndex() {
|
||||
bool configValid = (configBlock.magic == MAGIC);
|
||||
|
||||
if (! configValid) {
|
||||
#for $configItem in $configItems
|
||||
#if $configItem.label != "_"
|
||||
#if $configItem.type == "C"
|
||||
strcpy(configBlock.$configItem.key, "$configItem.default");
|
||||
#else if $configItem.type == "I"
|
||||
configBlock.$configItem.key = $configItem.default;
|
||||
#end if
|
||||
#end if
|
||||
#end for
|
||||
}
|
||||
|
||||
String buffer =
|
||||
"<!doctype html"
|
||||
"<html lang=\"en\">"
|
||||
" <head>"
|
||||
" <title>ESP8266 Thermometer Configuration Page</title>"
|
||||
" </head>"
|
||||
" <body>"
|
||||
" <h1>ESP8266 Configuration Page</h1>";
|
||||
|
||||
if (configSaved) {
|
||||
configSaved = false;
|
||||
buffer += "<h2>Configuration saved</h2>";
|
||||
}
|
||||
|
||||
buffer +=
|
||||
" <form action=\"/config\" method=\"GET\">"
|
||||
" <table>"
|
||||
#for $configItem in $configItems
|
||||
#if $configItem.label != "_"
|
||||
" <tr>"
|
||||
" <td>"
|
||||
" <label for\"$configItem.key\">$configItem.label</label>"
|
||||
" </td><td>"
|
||||
" <input type=\"text\" name=\"$configItem.key\" id=\"$configItem.key\" ";
|
||||
|
||||
#if $configItem.type == "C"
|
||||
buffer += " size=\"$configItem.length\" ";
|
||||
buffer += " value=\"";
|
||||
buffer += configBlock.$configItem.key;
|
||||
buffer += "\"";
|
||||
#else if $configItem.type == "I"
|
||||
buffer += " value=\"";
|
||||
buffer += configBlock.$configItem.key;
|
||||
buffer += "\"";
|
||||
#end if
|
||||
|
||||
buffer +=
|
||||
" />"
|
||||
" </td>"
|
||||
" </tr>"
|
||||
#end if
|
||||
#end for
|
||||
" <tr>"
|
||||
" <td colspan=\"2\">"
|
||||
" <button type=\"submit\">Save</button>"
|
||||
" </td>"
|
||||
" </tr>"
|
||||
" </table>"
|
||||
" </form>"
|
||||
" </body>"
|
||||
"</html>";
|
||||
|
||||
webServer.send(200, "text/html", buffer);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println("indexHtml request served");
|
||||
#endif
|
||||
}
|
||||
|
||||
void configServeGetConfiguration() {
|
||||
String arg;
|
||||
|
||||
#for $configItem in $configItems
|
||||
#if $configItem.label != "_"
|
||||
arg = webServer.arg("$configItem.key");
|
||||
#if $configItem.type == "C"
|
||||
strcpy(configBlock.$configItem.key, arg.c_str());
|
||||
#else if $configItem.type == "I"
|
||||
configBlock.$configItem.key = atoi(arg.c_str());
|
||||
#end if
|
||||
#end if
|
||||
#end for
|
||||
|
||||
configBlock.magic = MAGIC;
|
||||
|
||||
showConfiguration();
|
||||
|
||||
EEPROM.begin(512);
|
||||
EEPROM.put(EEPROM_ADDR, configBlock);
|
||||
EEPROM.commit();
|
||||
|
||||
Serial.println("EEPROM saved");
|
||||
|
||||
configSaved = true;
|
||||
webServer.sendHeader("Location", String("/"), true);
|
||||
webServer.send(302, "text/plain", "");
|
||||
//webServer.send(200, "text/html", "configuration saved");
|
||||
}
|
||||
|
||||
void showConfiguration() {
|
||||
Serial.println("Configuration is");
|
||||
|
||||
#for $configItem in $configItems
|
||||
Serial.print("$configItem.key = ");
|
||||
Serial.println(configBlock.$configItem.key);
|
||||
|
||||
#end for
|
||||
|
||||
Serial.println("---");
|
||||
}
|
||||
[/code]
|
||||
|
||||
Besides these generated files I also needed a framework to distinguish between "configuration mode" and "production mode" and in configuration mode to start the WiFi accesspoint.
|
||||
|
||||
Since I'm programming the ESP8266 in an Eclipse-based Arduino-environment, this is all done in the <code>setup()</code> and <code>loop()</code> function:
|
||||
|
||||
[code language="C"]
|
||||
void setup() {
|
||||
startTime = millis();
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting ...");
|
||||
#endif
|
||||
|
||||
pinMode(CONFIG_SWITCH, INPUT_PULLUP);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
EEPROM.begin(512);
|
||||
EEPROM.get(EEPROM_ADDR, configBlock);
|
||||
|
||||
Serial.print("Magic: ");
|
||||
Serial.println(configBlock.magic);
|
||||
|
||||
configMode = ((LOW == digitalRead(CONFIG_SWITCH)) || (configBlock.magic != MAGIC));
|
||||
|
||||
if (configMode) {
|
||||
#ifdef DEBUG
|
||||
Serial.println("Configuration mode");
|
||||
#endif
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
setupConfiguration();
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
Serial.println("Production mode");
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
showConfiguration();
|
||||
#endif
|
||||
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
setupProduction();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println("Started.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (configMode) {
|
||||
loopConfiguration();
|
||||
} else {
|
||||
loopProduction();
|
||||
}
|
||||
}
|
||||
|
||||
void setupConfiguration() {
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP(CONFIG_SSID);
|
||||
#ifdef DEBUG
|
||||
Serial.println("AP started");
|
||||
#endif
|
||||
|
||||
webServer.on("/", configServeIndex);
|
||||
webServer.on("/config", configServeGetConfiguration);
|
||||
webServer.onNotFound(configServeNotFound);
|
||||
webServer.begin();
|
||||
#ifdef DEBUG
|
||||
Serial.println("Webserver started");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loopConfiguration() {
|
||||
webServer.handleClient();
|
||||
}
|
||||
[/code]
|
||||
|
||||
|
||||
This code can be also found embedded into two of my projects. Find them at <a href="https://gitlab.com/wolutator/EspThermometer2" rel="noopener" target="_blank">https://gitlab.com/wolutator/EspThermometer2</a> and <a href="https://gitlab.com/wolutator/TouchSwitch" rel="noopener" target="_blank">https://gitlab.com/wolutator/TouchSwitch</a>.
|
||||
|
||||
')
|
29
posts/2018-02-22.01/article.m4
Normal file
29
posts/2018-02-22.01/article.m4
Normal file
@ -0,0 +1,29 @@
|
||||
define(`TITLE', `Home Automation Hub')
|
||||
define(`DATE', `2018-02-22')
|
||||
define(`CONTENT', `
|
||||
My home automation hub. (Photos inside)
|
||||
|
||||
<img class="alignnone size-full wp-image-872" src="https://a385e5.files.wordpress.com/2018/02/img_0304.jpg" alt="IMG_0304" width="4032" height="3024" />
|
||||
|
||||
<img class=" size-medium wp-image-873 alignleft" src="https://a385e5.files.wordpress.com/2018/02/img_0195.jpg?w=225" alt="IMG_0195" width="225" height="300" />
|
||||
|
||||
A Raspberry Pi runs <a href="https://homegear.eu" target="_blank" rel="noopener">Homegear</a> and <a href="https://github.com/hobbyquaker/homekit2mqtt" target="_blank" rel="noopener">homekit2mqtt</a>. It is equipped with two 866MHz radios for Homematic and MAX!.
|
||||
|
||||
Additionally an MQTT broker and the homegrown control software (<a href="https://gitlab.com/wolutator/dispatcher_ng" target="_blank" rel="noopener">https://gitlab.com/wolutator/dispatcher_ng</a>), which communicates with Homegear, homekit2mqtt, the MQTT433MHz bridge (see below) and other homegrown web clients via MQTT, resists on it.
|
||||
|
||||
<img class=" size-medium wp-image-876 alignleft" src="https://a385e5.files.wordpress.com/2018/02/img_0307.jpg?w=225" alt="IMG_0307" width="225" height="300" />
|
||||
|
||||
There is also a DIY MQTT to 433MHz bridge to control Intertechno and other 433MHz plugs (<a href="https://gitlab.com/wolutator/Mqtt433Gateway" target="_blank" rel="noopener">https://gitlab.com/wolutator/Mqtt433Gateway</a>).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<img class=" size-medium wp-image-881 alignleft" src="https://a385e5.files.wordpress.com/2018/02/img_0308.jpg?w=225" alt="IMG_0308" width="225" height="300" />
|
||||
|
||||
An finally a Philips Hue Bridge powered using a PoE adaptor for Philips and IKEA Tradfri bulbs, paired to Homegear.
|
||||
')
|
143
posts/2018-04-30.01/article.m4
Normal file
143
posts/2018-04-30.01/article.m4
Normal file
@ -0,0 +1,143 @@
|
||||
define(`TITLE', `Yet Another Debouncing Method')
|
||||
define(`DATE', `2018-04-30')
|
||||
define(`CONTENT', `
|
||||
You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.
|
||||
|
||||
One common approach is to ignore events in an ISR when they come too fast:
|
||||
|
||||
[code language="C"]
|
||||
void count() {
|
||||
static uint32_t lastEvent = 0;
|
||||
uint32_t currentEvent = micros();
|
||||
if (currentEvent > (lastEvent + configBlock.debounce)) {
|
||||
lastEvent = currentEvent;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(REED_PIN, INPUT_PULLUP);
|
||||
attachInterrupt(REED_PIN, count, FALLING);
|
||||
}
|
||||
[/code]
|
||||
|
||||
This works very good when only the tipping of a switch is relevant.
|
||||
|
||||
When also the time the button was pressed is relevant and when it is especially necessary to distinguish between a short and a long press this approach doesn't work anymore.
|
||||
|
||||
Since I couldn't remember the approaches I read about earlier I've sketched this state machine:
|
||||
|
||||
|
||||
<!--more-->
|
||||
|
||||
|
||||
|
||||
<img src="https://a385e5.files.wordpress.com/2018/04/20180430110848869_0001.jpg" alt="20180430110848869_0001.jpg" width="2332" height="3307" class="alignnone size-full wp-image-901" />
|
||||
|
||||
(The double-lined states are action-states which send out the related information.)
|
||||
|
||||
At least for me, this approach is working very reliable so far, I'm quite happy with it.
|
||||
|
||||
[code language="C"]
|
||||
enum tPressedState { psHIGH, psLOW, psACCEPTED_LOW, psLONG_START, psLONG_CONT, psLONG_CONT_SEND, psLONG_END, psSHORT, psINVALID };
|
||||
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
uint8_t buttonPin;
|
||||
tPressedState pressedState;
|
||||
tPressedState oldPressedState;
|
||||
uint32_t lastStateChange;
|
||||
} tButton;
|
||||
|
||||
tButton buttons[] = {
|
||||
{ 1, SWITCH_1, psHIGH, psINVALID, 0 },
|
||||
{ 2, SWITCH_2, psHIGH, psINVALID, 0 },
|
||||
{ 3, SWITCH_3, psHIGH, psINVALID, 0 },
|
||||
{ 0, 0, psINVALID, psINVALID, 0 } // END MARKER
|
||||
};
|
||||
|
||||
static void buttonHandler(tButton *button) {
|
||||
uint32_t currentMicros = micros();
|
||||
uint8_t buttonState = digitalRead(button->buttonPin);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (button->oldPressedState != button->pressedState) {
|
||||
Serial.print("Index ");
|
||||
Serial.print(button->index);
|
||||
Serial.print(", state changed from ");
|
||||
Serial.print(button->oldPressedState);
|
||||
Serial.print(" to ");
|
||||
Serial.print(button->pressedState);
|
||||
Serial.println();
|
||||
button->oldPressedState = button->pressedState;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (button->pressedState) {
|
||||
case psHIGH:
|
||||
if (buttonState == LOW) {
|
||||
button->pressedState = psLOW;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLOW:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
} else {
|
||||
if (currentMicros > (button->lastStateChange + configBlock.debounce)) {
|
||||
button->pressedState = psACCEPTED_LOW;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case psACCEPTED_LOW:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psSHORT;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros > (button->lastStateChange + (configBlock.longPress * 1000))) {
|
||||
button->pressedState = psLONG_START;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psSHORT:
|
||||
sendMsg(button->index, "PRESS_SHORT");
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_START:
|
||||
sendMsg(button->index, "PRESS_LONG_START");
|
||||
button->pressedState = psLONG_CONT;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_CONT:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psLONG_END;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros > (button->lastStateChange + (configBlock.longPressRepeat * 1000))) {
|
||||
button->pressedState = psLONG_CONT_SEND;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLONG_CONT_SEND:
|
||||
sendMsg(button->index, "PRESS_LONG_CONT");
|
||||
button->pressedState = psLONG_CONT;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_END:
|
||||
sendMsg(button->index, "PRESS_LONG_END");
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
default:
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
}
|
||||
[/code]
|
||||
|
||||
Find it embedded in the code of a small ESP8266-based switch thing I'm using in my home automation setup (home grown control code (https://gitlab.com/wolutator/dispatcher_ng), homegear (https://homegear.eu/) for device integration and openHAB (https://www.openhab.org/) as user interface) here: https://gitlab.com/wolutator/MySwitch.
|
||||
|
||||
')
|
Loading…
x
Reference in New Issue
Block a user