Here I will share some of my insights about embedded and PC software design and modern electronic hardware development. Everyone is welcome to engage into discussion.
Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts
Sunday, April 27, 2014
wxWidgets strange modal dialog crashes
Recently, I wrote one program with Code::Blocks version 12.11 and wxWidgets version 2.8.12. Logic of the program required invoking modal form (inherited from wxDialog, created with wxSmith). Once, during debugging, I found that the program continiously crashed after showing this modal form. The crashes usually occured either just after constructing of this dialog instance, or after a few seconds of this dialog being active. I revised all places in the source code which were somehow related with construction of this dialog, and with passing parameters of its construction and initialization. But I was unable to find any error(s) in the source code itself. At last, I got a flash of inspiration: I actually created this dialog from secondary ("worker") thread. After reimplementing this fucntion as running in the main thread (via combination of auxiliary window, SendMessageW with WM_USER and pointer to the structure with function parameters packed into WPARAM message argument, and MSWWindowProc functions), all crashes stopped. So the error was not in some line of the source code itself, but in the wrong architecture and lack of attention to this fact. The accompanying factor was that in previous version of the program, I used simple standard wxMessageBox function in that place. wxMessageBox apparently invokes WINAPI MessageBoxW function, and this works fine from secondary thread. But when I changed this to invoking of custom wxDialog form, in order to gain additional functionality, crashes began, and it took some time for me to understand where the problem resides.
Saturday, August 11, 2012
Broken WM_DROPFILES (Drag-and-Drop) functionality in Windows 7
Yesterday I spent at least one hour in finding and fixing cause of error due to which in one of my applications Drag-and-Drop functionality did not work in Windows 7 OSes, as was thankfully reported by one user. The reason traced to be that Microsoft decided to disallow applications to receive certain types of messages which are related with inter-process communication. This was done to enhance system security, of course. WM_DROPFILES is one of messages which are now not working by default. Now you need to explicitly tell OS that you want to receive and process this message, via calling appropriate API function: solution for problem with WM_DROPFILES in Windows 7. It is not difficult to call one more function during program initialization, but I'm really tired of various problems which arise from incompatibility between different Windows and Office versions. In this aspect, development for microcontrollers appeals to me much more, since there you can control everything, and tested procedures will not unexpectedly stop working because of some changes in underlying OS logic. I'm speaking here about MCU hardware+software projects where OS is still not necessary, (i.e., not high-performance high-cost complex monsters) and so you have some confidence in all parts of the system.
Sunday, June 10, 2012
Bugs in Windows Application Development
Today I at last have found time to fix some long-lasted bugs in one of my programs. Some of these bugs have been annoying users for about one year. They inconspicuously appeared after some phase of editing of source code. During fixing, I found two other previously completely overlooked bugs. They are not critical in nature, but annoying. It seems that this process (of finding and fixing bugs) can last forever.
Development for Windows OS, comparing to development for microcontrollers, allows you to employ many ready-to-use system (as well as third-party) libraries, thus freeing you from the task of implementing service code for yourself, but at the same time, bugs and inconsistencies in system and third-party libraries can force you to spend much time in efforts to figure out why your application is not behaving as you expected, and I'm pretty tired of it.
Conclusion is to test as big fraction of program's functionality as possible after every source code change.
Wednesday, March 14, 2012
How to reanimate Li-Ion or Li-Pol battery from your smartphone
Today I want to share my experience in repairing the Li-Pol smart battery in my HP iPAQ 1930. See my previous post on it.. My battery was marked with HP H1910 string on its paper box. The problem with it is if you'll leave device without even a single charge cycle for several weeks, it will discharge to a level from which it is impossible to initiate further recharging. If nominal voltage is 3.7 Volts, and you have allowed to discharge to about 3 V, this is the situation considered. A small piece of electronics, consisting of charge controller IC (integrated circuit), and a couple of power field (MOSFET) transistor keys, is placed between actual Li-Ion (or Li-Pol) battery and the outer contacts. Charge controller IC monitors voltage levels at the battery itself and outer contacts, opens necessary power key transistors, and communicate with host device via SMBus or other protocol to allow it to know state of the battery. Problem with discharging of a battery below certain level is that this controller IC stops working, so it is impossible to recharge the battery, since power key transistor have become permanently closed. But in many cases it is still possible to reanimate the smart battery.
To do this, cut off small pieces of plastic from both sides of the battery, to open access to the inner contacts of Li-Ion (Li-Pol) battery. You should see and have access to two metal stripes after this operation. Get laboratory DC power supply unit, with both constant current and constant voltage, modes of operating. I use SHENZHEN MASTECH HY3005D-3. Constant current mode is indicated by "C.C." red round LED at the front panel, while constant voltage -- by the nearby LED named "C.V.". My battery has capacity of 950mAh. The usual current for charging Li-Ion batteries is calculated as capacity x 0.2 (in the appropriate units, in my case, it would be 950 x 0.2 = 190 mA). Since we want to bypass control electronics, and will not monitor temperature of the battery, it would be safer to decrease this value, I think, two times will be enough, so I assumed charge current of 100 mA. I shortened outputs of one channel of SHENZHEN MASTECH HY3005D-3 power supply unit, and set short-circuit output current to this level. (Be aware also that maximum allowable current that USB port should be capable of providing by its spec, is 500mA. So if your device is charged through USB, do not exceed this value under any conditions. Even safer would be to use half of that value, that is, about 250 mA, as an upper threshold for charging current.) Then I set output voltage to nominal voltage of the battery, 3.7Volts in my case. After this, I connected output of power supply to inner batteries contacts. Initial current will be 100 mA, equal to short-circuit, and "Constant Current" LED should be active. During a few hours, the battery will be charging, after which voltage should rise to its nominal value (3.7 Volts in my case), current drops to near zero, and power supply switch to "Constant Voltage" mode. That's it. Now you can power off power supply, disconnected wires from battery, place it into your handheld device, and continue using it, without having to buy a new battery.
WARNING 1: Do not try to repeat the process without power supply with both "Constant Current" and "Constant Voltage" output mode, and without proper and carefully checked set-up values.
WARNING 2: Li-Ion batteries might fire and explode. It is safer to put the battery into the metal or other solid case during the process to avoid possible harmful accidents.
To do this, cut off small pieces of plastic from both sides of the battery, to open access to the inner contacts of Li-Ion (Li-Pol) battery. You should see and have access to two metal stripes after this operation. Get laboratory DC power supply unit, with both constant current and constant voltage, modes of operating. I use SHENZHEN MASTECH HY3005D-3. Constant current mode is indicated by "C.C." red round LED at the front panel, while constant voltage -- by the nearby LED named "C.V.". My battery has capacity of 950mAh. The usual current for charging Li-Ion batteries is calculated as capacity x 0.2 (in the appropriate units, in my case, it would be 950 x 0.2 = 190 mA). Since we want to bypass control electronics, and will not monitor temperature of the battery, it would be safer to decrease this value, I think, two times will be enough, so I assumed charge current of 100 mA. I shortened outputs of one channel of SHENZHEN MASTECH HY3005D-3 power supply unit, and set short-circuit output current to this level. (Be aware also that maximum allowable current that USB port should be capable of providing by its spec, is 500mA. So if your device is charged through USB, do not exceed this value under any conditions. Even safer would be to use half of that value, that is, about 250 mA, as an upper threshold for charging current.) Then I set output voltage to nominal voltage of the battery, 3.7Volts in my case. After this, I connected output of power supply to inner batteries contacts. Initial current will be 100 mA, equal to short-circuit, and "Constant Current" LED should be active. During a few hours, the battery will be charging, after which voltage should rise to its nominal value (3.7 Volts in my case), current drops to near zero, and power supply switch to "Constant Voltage" mode. That's it. Now you can power off power supply, disconnected wires from battery, place it into your handheld device, and continue using it, without having to buy a new battery.
WARNING 1: Do not try to repeat the process without power supply with both "Constant Current" and "Constant Voltage" output mode, and without proper and carefully checked set-up values.
WARNING 2: Li-Ion batteries might fire and explode. It is safer to put the battery into the metal or other solid case during the process to avoid possible harmful accidents.
Monday, January 16, 2012
Requiem to Phobos-Grunt
Yesterday, after about two months of orbiting the Earth on an intermediary, low-altitude elliptic orbit, Russian interplanetary station had finally fallen back to Earth, luckily into Pacific Ocean, not on some populated area.
Its short flight raised many questions to Roscosmos and even state's officials. Combined with several other satellite launch failures during last year, these questions are especially vital today. Maybe something in the area of top management of Roskosmos is really going wrong, maybe someone still think that world-class high-tech unique things can be developed for amount of money much less than world market suggests. Maybe something is broken at the bottom end of a technological chain, say poor quality control of production.
But here I want to point to only one side of the problem: nowadays, we have many strong rigorous math instruments that can be used to assess reliability and probability of failure for virtually any piece of hardware and software. Researches in the area of development of error-tolerant and reliable hardware and software systems allow one to employ many scientifically proved methods of designing and testing. This is XXI century, at last.
If scarce funding had really taken place, why main engineers and their bosses who were responsible for device subsystems could not just say: "Hey, guys, this is not enough to achieve the project's goals. You either will give us enough resources (time, money, people, equipment, etc.), or we will not sign for the work.". It seems that something is broken in the whole chain of decision making in Roskosmos. Sadly, but such conclusion came to mind after reading news.
Its short flight raised many questions to Roscosmos and even state's officials. Combined with several other satellite launch failures during last year, these questions are especially vital today. Maybe something in the area of top management of Roskosmos is really going wrong, maybe someone still think that world-class high-tech unique things can be developed for amount of money much less than world market suggests. Maybe something is broken at the bottom end of a technological chain, say poor quality control of production.
But here I want to point to only one side of the problem: nowadays, we have many strong rigorous math instruments that can be used to assess reliability and probability of failure for virtually any piece of hardware and software. Researches in the area of development of error-tolerant and reliable hardware and software systems allow one to employ many scientifically proved methods of designing and testing. This is XXI century, at last.
If scarce funding had really taken place, why main engineers and their bosses who were responsible for device subsystems could not just say: "Hey, guys, this is not enough to achieve the project's goals. You either will give us enough resources (time, money, people, equipment, etc.), or we will not sign for the work.". It seems that something is broken in the whole chain of decision making in Roskosmos. Sadly, but such conclusion came to mind after reading news.
Friday, December 30, 2011
Attentiveness in engineering work
The day before yesterday I had finally finished firmware in VHDL which is burned into Altera CPLDs in my design. Now all works fine, including surrounding digital schematics.
Unfortunately, I spent about two months on this part of project instead of planned four weeks. The reason is lack of attention during initial schematics development and VHDL program writing. Little logical error in VHDL program and lack of thorough test simulations caused me to solder several wires to key logic nets of the design under consideration, connect them to special debug connector and examine its pins with oscilloscope. Physical layout of the two mezzanine PCBs does not allow to access all logic nets directly with oscilloscope probes. At the end, error in firmware was found and fixed, but at price of extra time and nerves.
After VHDL firmware was fixed, the device still did not function as it should. The reason traced to be a subtle difference in my schematics in comparison with third-party device to which my design should be compatible. My schematics was right, but incompatible with third-party software from manufacturer of that device. This was fixed by means of one 0603 resitor and two equipment wires.
Finally, this part of device passed all tests.
The lesson learned is the impermissibility of neglecting thorough and attentive requirement analysis and creating simulation tests during initial design phase.
Unfortunately, I spent about two months on this part of project instead of planned four weeks. The reason is lack of attention during initial schematics development and VHDL program writing. Little logical error in VHDL program and lack of thorough test simulations caused me to solder several wires to key logic nets of the design under consideration, connect them to special debug connector and examine its pins with oscilloscope. Physical layout of the two mezzanine PCBs does not allow to access all logic nets directly with oscilloscope probes. At the end, error in firmware was found and fixed, but at price of extra time and nerves.
After VHDL firmware was fixed, the device still did not function as it should. The reason traced to be a subtle difference in my schematics in comparison with third-party device to which my design should be compatible. My schematics was right, but incompatible with third-party software from manufacturer of that device. This was fixed by means of one 0603 resitor and two equipment wires.
Finally, this part of device passed all tests.
The lesson learned is the impermissibility of neglecting thorough and attentive requirement analysis and creating simulation tests during initial design phase.
Wednesday, October 5, 2011
Stupid Connector Pinout Problem
Today I spent half of a working day correcting the problem with wrong IDC2-10 connector pinout. The usual pattern in which pins are ordered is as follows:
UPD: They fixed this error in the latest version of the manual. I should had to check for the latest version before using it.
1 3 5 7 9 2 4 6 8 10In the User's Manual of industrial PC, to which I must connect, the picture looks like:
1 2 3 4 5 6 7 8 9 10I was slightly alarmed when I saw it the first time, but I thought that this is their right to re-order pins on their own module. Today, when I tried to get my PCB and this third-party industrial PC to work together, it was revealed that pins on its socket are actually ordered in a usual way, as shown in the first block. The unusual order that I observed in the manual was result of mere inaccuracy of their documentation writer. Strictly speaking, this is not my fault, but if I would check the actual ordering of pins before working on PCB, it would save me several hours of my life. Instead, today I have had to do some mounted-wire soldering on all manufactured devices to bring PCB footprints pinout to an actual state.
UPD: They fixed this error in the latest version of the manual. I should had to check for the latest version before using it.
Monday, September 26, 2011
Wrong Pin Numbers in PS/2 socket
Today I spent almost the whole working day to make (solder) a few adapters to remedy my PCB designing error. The problem was that I used MINIDIN-6 surface-mount female socket on my PCB, and I incorrectly routed PCB tracks to pins of that socket. It revealed that I used mirrored view of the socket when direct, non-inverted view should be used. Only one additional checking procedure would save me almost a whole working day.
PS/2 connector on Wikipedia
PS/2 connector on Wikipedia
Friday, September 16, 2011
Electronic Component Misorientation Problem
Today the first preproduction batch of my devices, consisting of four PCBs (Printed Circuit Boards), was finally completely mounted, and I began to power them up in order to test the mounting accuracy and device functionality. It was revealed during mounting that I had placed some components too close to each other, although this will not prevent embedded software developers from using the devices to debug their firmware. When I started to bring the live into the device, I found that at one position, on all devices, stabilitrons were mounted in opposite polarity. It seems that assemblers who performed actual soldering, are accustomed to the fact that diodes' Anode pole are usually goes to positive polarity, and Cathode pole - to negative. This is true for simple forward usage of regular and shottky diodes, but stabilitrons need to be used in reverse direction. I marked where the Anode should be on assembly drawing, nevertheless it seems that assembler was guided by datasheet, where Anode mark is showed, and polarity of PCB padstacks. I'm thinking about resorting to using SOT-23 case for this component in second version of a scheme (for those who are not familiar with it: this is 3-leads case, it have 2 leads on one side and one on another, thus it is impossible to place it in wrong orientation). It may be _slightly_ more expensive than currently used 2-leads case, but it will leave us from necessity to think about right orientation and to control it.
It seems, that many engineering decisions are often driven by similar motivation - to ease manufacturing and/or repairing processes, at price of slightly increasing components cost.
It also reminds me that responsibility of everyone who design any type of interfaces, is to make every interface as clean and consistent as possible, and to make sure that working with this interface requires from user absolutely minimum of possible knowledge of a system.
SOT-23 drawing
It seems, that many engineering decisions are often driven by similar motivation - to ease manufacturing and/or repairing processes, at price of slightly increasing components cost.
It also reminds me that responsibility of everyone who design any type of interfaces, is to make every interface as clean and consistent as possible, and to make sure that working with this interface requires from user absolutely minimum of possible knowledge of a system.
SOT-23 drawing
Saturday, September 10, 2011
About testing
While working on my software projects, I often encountered a situation when almost all was ready for releasing a next version, but after starting final tests on different systems, many unexpected bugs were revealed. Sometimes after a small change in one part, other, presumably totally unrelated functionality, started to work wrong, sometimes the program worked right on one OS, but not on another, sometimes something very strange at first look appears.
The end conclusion that I have drawn is that testing should never be neglected or shrunk. It takes time, but if not done well, the end users will be whose who will find bugs and errors.
Similar thing has to be said about hardware testing. You should never be confident that a given part of device is working properly if it was not properly and thoroughly tested.
The end conclusion that I have drawn is that testing should never be neglected or shrunk. It takes time, but if not done well, the end users will be whose who will find bugs and errors.
Similar thing has to be said about hardware testing. You should never be confident that a given part of device is working properly if it was not properly and thoroughly tested.
Hard-to-find lack of variable initialization issue
Another bug which I once encountered, raised from using local (i.e., stack) method (or procedure/function) variables of record type. When you forget to assign some value to simple local variable, and then try to use it, Delphi compiler warns about it:
To illustrate what has been said, take a look at the following code:
Compiler will not say anything on A(Foo) source code string.
The following string
Variable "VarName" might not have been initializedBut when you have record-type local variable, and somewhere passes it as a parameter to another function, the Delphi (7) compiler does not check that you have initialized all fields. It will silently use whatever values was in memory at the call stack on the location that was taken for such record field. So you must be especially careful when using local record vars. Doing ZeroMemory on all such records at the very beginning of the function (or procedure/method), seems to be a good habit, otherwise it is a big chance that you will lose some valuable time trying to understand why the program behaves so strange.
To illustrate what has been said, take a look at the following code:
type
TFoo = record
a, b: Integer;
end;
procedure A(Foo: TFoo);
begin
end;
procedure B;
var
Foo: TFoo;
begin
A(Foo);
end;
Compiler will not say anything on A(Foo) source code string.
The following string
ZeroMemory(@Foo, SizeOf(Foo));before A(Foo), if will not make your program free of logical errors, but at least will make the program behavior predictable and reproducible.
Hard-to-find object variable overwriting issue
I write software programs in Delphi, version 7 (also in C++ Builder, but this post is about Delphi). Once I decided to optimize the code and to add "const" specifier to all parameter declarations of methods which are not changed in the method body itself. This is recommended for better readability and for performance reasons. For variables of WideString type, if you do not use "const" specifier in function parameters list, the compiler will create new copy of passed WideString variable upon function entry and release it after function will return. This is because WideStrings are not reference-counted, as opposed to AnsiStrings. But when "const" is specified, the compiler passes pointer to string content (2-byte-wide chars) as is. So, I added "const" specifier everywhere when applicable, and did not receive any copiler warning. But during following testing, it turned out that something had became broken after this change. Strange error sometimes appears, which resulted in wrong value in some object field of type WideString. This error did not appear always, and only on one of two tested MS Windows versions.
I started to seek for the reason, and finally it traced to using WideString-type field of the object which passed as now "const" parameter. The code was something like:
The compiler did not detect any issues, yet the problem was
that after invoking of SetProperty, the previous pointer to WideChars array contained in FPropValue field, and in APropValue parameter, becomes invalid, but this old pointer value was used when invoking DoSomethingElse method.
I fixed the problem by eliminating "const" specifier from DoSomething declaration.
Be aware of such a pitfall!
I started to seek for the reason, and finally it traced to using WideString-type field of the object which passed as now "const" parameter. The code was something like:
procedure TFoo.SetProperty(const APropValue: WideString); ... begin ... FPropValue := APropValue; end; .... procedure TFoo.DoSomething(const APropValue: WideString;...); ... begin ... SetProperty(APropValue); DoSomethingElse(APropValue); end; procedure TFoo.DoSomething2(...); ... begin ... DoSomething(FPropValue); ... end;
The compiler did not detect any issues, yet the problem was
that after invoking of SetProperty, the previous pointer to WideChars array contained in FPropValue field, and in APropValue parameter, becomes invalid, but this old pointer value was used when invoking DoSomethingElse method.
I fixed the problem by eliminating "const" specifier from DoSomething declaration.
Be aware of such a pitfall!
Subscribe to:
Posts (Atom)