There are multiple versions of hardware and firmware for these modules. After digging around the internet for a few days it appears that there are at least 3 different microcontroller chipsets used in these modules:
- STM8S003F3 SOIC-20
- N76E003 SOIC-20
- Unmarked SOIC-16
These boards also have different production marks on the PCB e.g.
- LPWM - as shown in the picture above
- XY-LPWM
- JZ-LPWM
- HW-753
- HW-753 V3.0 - The version shipped to me by Hobby Components in Nov 2023
I have seen reports of different versions returning different responses to commands and even some boards that could not be made to communicate over the serial port. It would appear that the buyer is at the mercy of whatever hardware and firmware that is supplied. I can find no documented source to determine what firmware version is installed.
The major issue with attempting to communicate with devices like these over usb is the delay introduced by the usb stack and the internal buffers on the usb-serial adaptor. The microcontroller needs to interpret the message and send the response to the usb adaptor. The adaptor stores this response in it's internal buffer and waits until either the buffer is full or some device specific timeout occurs before transmitting the data over usb. The OS usb stack also introduces further delays due to the use of internal buffers for both usb messages and serial rx/tx buffers. So there can be quite a delay between the microcontroller sending data out from it's uart until it becomes available to the user program.
The following is a crude command line program, written in C#, for setting the frequency and pulse width duration.
/* File: setpwm.cs
* Date: 16 Nov 2023
*
* This program demonstrates serial access to the XY-LPWM Module
* using C#.
*
* This code was written and tested against the following hardware:
*
* HCMODU0134 1Hz to 150KHz PWM Frequency Generator Module (HW-753 V3.0)
* FT232RL USB-Serial TTL 3V3 Adaptor Module
* Medion Erazer Laptop
* Windows 10 Home
*
* Usage:
*
* setpwm COMx Fxxx Dxxx
*
* Use 'Fxxx', 'Fx.xx', 'Fxx.x' or 'Fx.x.x' to set frequency
* Use 'Dxxx' to set duty cycle
*
* Example:
*
* setpwm F3.14 D059
*
* Example Response:
*
* F3.14 OK
* D059 OK
* F=3.14KHz D= 59%
*
* Disclaimer:
*
* This code is for demonstration purposes only and is not intended
* as an example of production quality code.
*/
using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
class SetPWM
{
static void Main(string[] args)
{
if (args.Length == 3) {
SerialPort mySerialPort = new SerialPort(args[0], 9600, Parity.None, 8, StopBits.One);
try {
mySerialPort.Open();
// send the first parameter
mySerialPort.Write(args[1]);
// wait for device to respond & usb buffers to flush
Thread.Sleep(1000);
// read the response
string response = mySerialPort.ReadExisting();
// check the response 'DOWN' is OK anything else is a problem
if (response.Contains("DOWN")) {
Console.WriteLine("{0} OK", args[1]);
} else {
Console.WriteLine("Bad Command {0}", args[1]);
}
// send the second parameter
mySerialPort.Write(args[2]);
// wait for device to respond & usb buffers to flush
Thread.Sleep(1000);
// read the response
response = mySerialPort.ReadExisting();
// check the response 'DOWN' is OK anything else is a problem
if (response.Contains("DOWN")) {
Console.WriteLine("{0} OK", args[2]);
} else {
Console.WriteLine("Bad Command {0}", args[2]);
}
// get the device status
mySerialPort.Write("read");
// wait for device to respond & usb buffers to flush
// longer delay due to longer message
Thread.Sleep(1500);
// display the device status, varies by model/firmware
Console.Write(mySerialPort.ReadExisting());
mySerialPort.Close();
} catch (Exception ex) {
Console.WriteLine("Error: {0}", ex.Message);
}
} else {
// display usage if wrong number of arguments supplied
Console.WriteLine("Invalid number of arguments");
Console.WriteLine();
Console.WriteLine("Usage:");
Console.WriteLine(" setpwm COMx Fxxx Dxxx");
Console.WriteLine();
Console.WriteLine("Use 'Fxxx', 'Fx.xx', 'Fxx.x' or 'Fx.x.x' to set frequency");
Console.WriteLine("Use 'Dxxx' to set duty cycle");
Console.WriteLine();
Console.WriteLine("Example:");
Console.WriteLine(" setpwm F3.14 D059");
}
}
}
/*
* The author of this work hereby waives all claim of copyright (economic
* and moral) in this work and immediately places it in the public domain;
* it may be used, distorted or destroyed in any manner whatsoever without
* further attribution or notice to the creator.
*/
You do not require Visual Studio or any other IDE to compile this code. All versions of Microsoft Windows that I have used with the .Net framework installed have also contained a minimal C# compiler. This compiler can be found in the .Net Framework folder, for example:
C:\Windows\Microsoft.NET\Framework\vx.xxxx\csc.exe
or
C:\Windows\Microsoft.NET\Framework64\vx.xxxx\csc.exe
where vx.xxxx is the version of .Net you have installed eg. v3.5, v4.0.30391 etc.
To compile the program from the command line simply open a command prompt and cd to the location of the source file then invoke the compiler using:
C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe setpwm.cs
This will produce the executable file
setpwm.exe
.
To use the program from the command line type:
setpwm COMx Fxxxx Dxxx
where:
COMx is the COM port the device is on e.g. COM6
Fxxxx is the frequency desired.
Use Fxxx for Hz e.g. F123 for 123Hz
Use Fx.xx for 1KHz to 9KHz e.g. F3.14 for 3.14KHz
Use Fxx.x for 10KHz to 99KHz e.g. F36.5 for 36.5KHz
Use Fx.x.x for 100KHz to 150KHz e.g. F1.2.3 for 123KHz
Dxxx is the duty cycle percentage, must be a 3 digit integer with leading zeros e.g. 050 is 50%. 000 and 100 are legal values.
The D and F arguments must be upper case.
I can only state that this code works reliably on my system with my hardware, your mileage may vary, but I hope this code is a useful starting point for someone.