Adding backlight control to Waveshare 7″ touchscreen
I can’t say enough good things about OctoPrint. I can control either of my printers from any computer in my house, starting prints, aborting prints, uploading gcode or slicing, visualizing and the logo is quite endearing as well. With the addition of plugins, the web UI took a leap forward when BillyBlaze wrote TouchUI which adds a simpler finger-friendly interface that works well on tablets and phones. Being able to abort a print and restart it from an old Nexus 7 2012 tablet without having to fire up a computer really saved me a lot of trips back and forth. The Nexus tablet does an OK job, but it always chugs for a while when first woken up– something that doesn’t help when you’re quickly trying to stop a print that is in catastrophic failure mode. Recently a 7″ LCD panel came into my possession for use doing development to replace an old 24″ display that was taking far too much space on my desk just to be a temporary head of an embedded Linux system and I hooked it up to a Raspberry Pi to try it out running the TouchUI locally against OctoPrint.
Alarm Monitor from MQTT, not ADT
When I bought my house it came equipped with one of those olde fashioned house alarm systems where the central panel is wired into the phone landline. I never could quite wrap my head around why an alarm monitoring service, which is essentially just a reverse-telemarketing business, costs so much money to run. They’re paying people next to nothing to make a short phone call but charging customers $50 a month for it. I don’t even have a hard-wired phone so that’s another $25/month on top of that. I had the system so why not modernize it a bit?
The alarm zone circuitry is pretty simple, a wire runs to the sensor which is normally closed and opens when the sensor is triggered. To guard against an intruder simply shorting the wires, an “End of Line” resistor is installed in the panel at the end of every zone’s wire. This gives the alarm system 3 potential voltages
- 0V – Shorted, Alarm
- 12V – Open circuit (sensor is activated), Alarm
- ~5V – Normal
I just needed a way to monitor the zone wire voltages and publish them into my MQTT network. I first considered resistor dividers to drop the voltages down to 0V-3.3V range and then using an ATmega’s ADC to measure them, but I was concerned the extra resistors might change the functionality of the alarm circuit. I just needed to compare the voltage to some reference voltages and give me a simple digital 0 or 1 depending on the alarm voltage.
When AREF isn’t AREF (yet)
I’d often noticed that measuring analog inputs on my ATmega, that the first round of values usually differed substantially from subsequent values. The datasheet even warns of a similiar-sounding issue:
The first ADC conversion result after switching reference voltage source may be inaccurate, and the user is advised to discard this result.
Knowing that the Arduino libraries don’t actually set the reference voltage until the time the first sample is made, it seemed logical that these first samples were an artifact of the voltage changing. However, it wasn’t just the first sample, or the first couple samples. It could take dozens of samples before the value returned had stabilized (i.e. stopped increasing by more than 2 LSB). Being a boot-only issue. I was content to ignore it until I started trying to read the on-chip temperature sensor.
(more…)
Grill Control Project Part 3
Hardware construction time. Note: this is for the v3 version of the HeaterMeter controller.
I ordered the Arduino Duemilanove and buttons from SparkFun, the WiShield 2.0 from AsyncLabs, and the components and blower from DigiKey. What you end up with is a whole dining room table full of parts.
(more…)
Grill Control Project Part 2
Based on Bob’s lead, I chose the Arduino platform as my microcontroller. Specifically the Arduino Duemilanove.
- ATmel ATmega168 Micocontroller
- RISC 8-bit CPU running at 16MHz / 5V
- 32kB code space (30,720 bytes usable)
- 2kB RAM
- 1kB Flash storage EEPROM
- Integrated ADC, Digital PWM, SPI bus interface, UART TTL Serial
- C/C++ programming environment
Yeah 2kB of RAM. For comparison, my blog front page is currently 250 times that. 30kB of usable code space? The default Delphi Project1.exe baseline with no user code is 13 times as large. Squeezing everything in to that space seems like a challenge: a web server, LCD and buttons with a menuing system, and I reckon it should control a grill too.
This post was going to be about the platform, but that’s boring. Let’s just jump into the project and I’ll introduce things as needed.
(more…)
Software Guy Builds Hardware
or: How I Learned to Stop Working at Making Things Burn, the Great Grill Control Project part 1.
Foods cooked on the grill are at the top of my food chain. I am a main predator of Kingdom Animalia, Phylum Grilledatas. The problem with grilling is that the grill is outside, in a place where it is usually hot, far away from my beer, and entertainment-starved unless observing the negative gravitropism of stenotaphrum secundatum is your thing. Barbecue further aggravates the situation by requiring long cook times which may even necessitate losing sleep. Sure you can “barbecue” in an oven, “barbecue” cooked in an oven isn’t barbecue all and bears as much resemblance to the real deal as K-rab does to stone crab. There has to be smoke, and the easiest way I know to get smoke it to light something on fire.
Contrary to what Frankenstein says, fire isn’t always bad, but it can require a good bit of fiddling make it do what you want, sort of light plate spinning. It certainly is a lot easier than plate spinning and you can’t eat anything when you’re done spinning plates for 8 hours, so I’m not sure why I used that analogy. Anyway, I’ve tried the Alton Brown Electric Pot smoker concept, which produced lackluster results even after several attempts and equipment swaps. The initial solution was to step up to the big leagues and buy a Big Green Egg, the self-described “World’s Best Smoker and Grill!” (emphasis theirs).
(more…)
Proper Timing with GetTickCount()
Often programmers are faced with implementing timers for short-period operations, anywhere from the sub-second to a few hours. These sort of timers are typically used in timeout operations, like idle connection timeouts, stale cache timeouts, and fade timers, but are also used in basic discrete physics calculations, input debounce timers, and timeslice allocations. In these applications I like using GetTickCount().
More information on why I like it and why to choose it over other timing options follow after the break.
(more…)
How TaskDialogIndirect() can turn Cancel into Yes
User Interface designers are rather sadistic. In the year 3000, when suicide booths will be commonplace, a User Interface designer will be the sort of fellow who places the “Stab Me to Death” button adjacent to the “Enjoy a Lovely Cup of Tea” button on the Slurp ‘N Spear vending machine down at the local Automat. If you’re interested in getting repeat business, you’ll probably want to confirm that the consumer would rather purchase a gut full of twisting metal instead of a mouthful of dried leaves in water.
Consider the following code analog to this situation, where the Delete button looks too much like, or is placed to close to the Save button in a toolbar. As a defensive programmer you safeguard the delete function with a confirmation:
if MessageDlg('This action is not undoable.'#13 + 'Are you sure you want to delete all your work?', mtConfirmation, [mbYes,mbNo], 0) = mrNo then exit; DoDeleteAllYourWork();
This works fine and the early bailout situation is preferable in my book when the code of DoDeleteAllYourWork() actually follows inline. The code is written, compiled, shipped and you forget all about it until a few years later someone calls up spitting venom because they pressed Escape and your app deleted their work. What has occurred is a subtle issue created by Delphi switching from their own MessageDlg to Vista’s powerful TaskDialogIndirect() API when you enable runtime themes in your project options.
(more…)
Determining ThreadingModel in a Delphi Application
I has occurred to me that someone might need to determine their COM threading model from inside their application. This could be useful for some ASSERT() code or perhaps as part of a unit test. From my last blog post, you’ll recall that this information is stored in an opaque structure located in each thread’s Thread Environment Block (TEB). Actually quite simple to do, with original credit going to John Robbins’ Bugslayer Column from the old MSJ magazine.
{ uses ActiveX; Ported from John Robbins - Microsoft Systems Journal Bugslayer Column - October '99 http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.aspx } function DebugCoGetThreadingModel : integer; const OLE_APT_MASK = $0080; OLE_FREE_MASK = $0140; var dwOLETLS: Cardinal; dwFlags: Cardinal; begin asm // Get TEB mov eax, FS:[018h] mov eax, [eax+0f80h] mov dwOLETLS, eax end; { Not initialized } if dwOLETLS = 0 then begin Result := -1; exit; end; dwFlags := PCardinal((dwOLETLS + $0C))^; if ((dwFlags and OLE_APT_MASK) = OLE_APT_MASK) then Result := COINIT_APARTMENTTHREADED else if ((dwFlags and OLE_FREE_MASK) = OLE_FREE_MASK) then Result := COINIT_MULTITHREADED { Unknown } else Result := -2; end;
And some sample usage code
case DebugCoGetThreadingModel of -2: Label1.Caption := 'Unknown'; -1: Label1.Caption := 'Not initialized'; COINIT_APARTMENTTHREADED: Label1.Caption := 'COINIT_APARTMENTTHREADED'; COINIT_MULTITHREADED: Label1.Caption := 'COINIT_MULTITHREADED'; end;
John also has an excellent blog of his own which is which is a fantastic low-level technical resource. Speaking of old magazines, I just discovered the Bug of the Month ad that has appeared in Dr Dobbs for nearly the past 20 years has an online archive. Head over to Gimpel Software if you’re up for some C-based brain exercises.
Debugging a Delphi Lockup with Windbg
While the Delphi debugger is quite good, there are some instances when it isn’t quite good enough.
- Your application is crashing remotely The worst place for an application to fail is when there is no debugger available. Usually these problems can be corrected via the “Works Fine Here” solution. Unfortunately most bug-tracking systems lack this option to close tickets.
- Lack of symbol information The best trace you can get in the debugger shows a thread balls deep into Windows API calls for no apparent reason. Some resolution can be gained from the DLL export addresses but without proper symbol information this isn’t enough detail.
The solution to both these scenarios is to use Microsoft’s free debugger WinDbg, available as part of the Debugging Tools for Windows package. You’ll need the version for the host platform where the trace will occur. This means get the 64-bit if you’re debugging on Win64 even if your app is 32-bit. You’ll also need the map2dbg utility, originally by Lucian Wischik.
(more…)