All posts by Per Magnusson

Fixing Sportident Thermal Printer Issues

The youth section of my orienteering club has a Sportident thermal printer connected to an SI station for use on trainings. This has worked fine for a few years, but for some reason it started printing garbage and I was asked to have a look at it.

I had never used the printer before, but I started troubleshooting. The SI station had old firmware, so I updated that using Sportident Config+, but this did not help. At first I did not get the printer to print anything, but that turned out to be because I had failed to realize that the SI logo was actually a hidden power button one has to press briefly to turn the printer on or off. After the printer was powered on, it did indeed print garbage when I tried to print the contents of an SI card.

The printer is a Martel MCP7830-242 printer with a serial port and I was able to find a manual for it. It turns out a customized manual is also available from Sportident. I suspected the problem might be that the printer was set up to use an incorrect baud rate and I first tried to set the SI station in its two possible states, namely 4800 and 38400 bauds, but that did not help. The manuals have instructions on how to change the baud rate on the printer and according to those instructions, one should keep the power button pressed a couple of seconds until the LED starts blinking, then one should press the button four times and wait for the LED to blink four times (this enters the baud setting mode), then press the button six times to select 4800 baud. Unfortunately this did not help and the printer still printed garbage.

I then decided to talk to the printer from a PC and I wrote a small Python script to try to send commands to it at different baud rates. After some fiddling around, the printer started responding, but at the unexpected baud rate of 600 bauds!

The Python code is shown at the end of this post in case someone is interested.

I retried the baud rate setting, but still with the result of getting the printer to accept 600 bauds. A note above the tables in the manual says one should do a single button press to select 19200 bauds, but the table says the button should be pressed five times. This made me try to press the button three instead of six times (4800 comes two steps after 19200 in the table) and after this, the printer started working at 4800! So the correct sequence for setting the baud rate to 4800 is this:

  1. Printer is off
  2. Hold down the button for a few seconds until the LED starts flashing.
  3. Press the button 4 times.
  4. Wait for the LED to flash 4 times.
  5. Press the button 3 times.
  6. Wait for the LED to flash 3 times.
  7. Done!

After I got it all to work I realized that one can check the mode of the printer in the following way:

  1. Printer is off
  2. Hold down the button for two seconds.
  3. The printer prints its status, including the baud rate.

If I had known this from the start I might have solved this much quicker.

Below is the Python code.


#! /usr/bin/python

"""
com-port-sender.py

Rev 0.1, 2016-09-28
Per Magnusson, Axotron, axotron.se/blog

This code is public domain and comes with absolutely no warranty. Enjoy!

Send some data on a serial port to test a Martel/Sportident MCP7830 printer.
"""

from __future__ import print_function
import serial
import serial.tools.list_ports
import sys
import time
import msvcrt
import struct


# Look for a COM port that might have a serial port adapter connected
portfound = False
ports = list(serial.tools.list_ports.comports())
for p in ports:
    print(p)
    print(p[1])
    if "Prolific" in p[1]:
        print("Found port on " + p[0])
        if not portfound:
            portname = p[0]
            portfound = True
            print("Using " + portname)
        else:
            print("Ignoring this port, using the first one that was found.")

if portfound:
    ser = serial.Serial(portname, 4800, timeout=0.1)
else:
    print("No good serial port found. Exiting.")
    time.sleep(10)
    sys.exit("No good serial port found.")


def to_printer(ser, data):
    for b in data:
        print("{:d} ".format(ord(b)), end="")
    ser.write(data)
    print("")

def send_ESC(ser):
    to_printer(ser, b'\x1b') # 27 == ESC

def send_NULL(ser):
    to_printer(ser, b'x\00')

def set_sweden(ser):
    send_ESC(ser)
    to_printer(ser, b'R5')

def set_mode_default(ser):
    send_ESC(ser)
    to_printer(ser, b'!\x00')

def reset_printer(ser):
    send_ESC(ser)
    to_printer(ser, b'\xff')

def reset_printer2(ser):
    send_ESC(ser)
    to_printer(ser, b'@')

def printer_self_test(ser):
    send_ESC(ser)
    to_printer(ser, b'\xfe')

def printer_move_fwd(ser):
    send_ESC(ser)
    to_printer(ser, b'J\x08')

def printer_print(ser):
    send_ESC(ser)
    to_printer(ser, b'd\x01')

def print_something(ser):
    to_printer(ser, b'abc\x0d\x0a\x0c')


#set_sweden(ser)
#printer_self_test(ser)
#reset_printer(ser)
#reset_printer2(ser)
#set_mode_default(ser)
#printer_move_fwd(ser)
#to_printer(ser, b'abc\x0d\x0a\x0c')
#printer_print(ser)

rates = [300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200]

for rate in rates:
    print('baud: {:d}'.format(rate))
    ser.setBaudrate(rate)
    print_something(ser)
    time.sleep(5)

ser.close()

Setting up an STM32 development environment on Windows

Background

In recent years, I have been using Arduinos and Teensys with the Arduino environment and FRDM boards using the mbed web-based environment for small processor-controlled projects. However, when doing a project with a custom PCB that includes the processor, these platforms and environments are no longer quite as attractive.

Sure, one can use the same processor as exists on some Arduino and program it with the proper Arduino bootloader and continue working in the Arduino environment. Or one could use e.g. an STM32 processor that exists on one of the boards supported by mbed and program it via the ST-link of such a board. But when moving away from exactly the processor variants that exist on mbed-supported boards, one might run into trouble as ordinary users do not seem to be able to configure the mbed environment for other processor variants. Also, the fact that mbed resides in the cloud could be downside depending on personal preferences.

For these reasons I wanted to set up a local development environment so that I could use some reasonably modern 32-bit ARM processor on a fully custom board. I also wanted a solution that did not cost any money, so Keil and IAR are out of the question. I opted to use STM32L052C8T6 from the the STM32 L0 family of low-power Cortex M0+ parts as it seemed to have the features and performance I needed while also being power efficient and thereby possibly supporting battery operation at some future version of my design. An advantage of STM32-processors from ST is that they can be programmed via the ST-Link that is built into every inexpensive (~$10-15) Discovery or Nucleo development board. So no expensive programmer is necessary.

There seems to be more than one option for free development environments for STM32 processors and I first tried to set up Eclipse with the GNU ARM Eclipse plugins. After a lot of time reading various posts on the GNU ARM Eclipse website and installing all the bits and pieces I still was not able to compile the configuration and initialization code generated by STM32CubeMX. Probably someone with more experience, patience and knowledge of Eclipse than me could get this to work, but after a lot of fiddling around with settings of include and code directories I tried another option, namely the SW4STM32 environment provided by the company Ac6.

Tool installation

SW4STM32 is a free (but requires registration) tool based on Eclipse. Although I use it on Windows, it is also available for Linux and MacOSX. I guess most of the below instructions apply for non-Windows installations as well.

This is how to install SW4STM32:

  1. Create an account on http://www.openstm32.org/HomePage and log in.
  2. Follow the instructions under Documentation > System Workbench for STM32 > Installation manual, or continue below.
  3. Download the appropriate (32-bit or 64-bit version) of the installer from http://www.openstm32.org/Downloading+the+System+Workbench+for+STM32+installer. It is important to select the correct architecture (32/64) to make the ST-Link debug probe work.
  4. Run the installer.
  5. If you get a warning about JavaRE, you need to install the appropriate Java runtime from Oracle. It has to have the same architecture (32/64-bit) as SW4STM32.
  6. Click through the dialogs. Select C:\Ac6\SystemWorkbench or some other suitable path without spaces in the folder names as installation directory.
  7. Launch the program when the installation is finished and go to Help > Check for updates to update to the latest version of all the components.

To get started with the software development, one can use the tool STM32CubeMX from ST to generate configuration and initialization code:

  1. Download STM32CubeMX from http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-configurators-and-code-generators/stm32cubemx.html
  2. Install the tool.
Screenshot of CubeMX
Screenshot of CubeMX

It is not immediately obvious how to use CubeMX such that the resulting code is easily imported into SW4STM32. I learned this the hard way, but found the solution on: http://www.openstm32.org/Importing+a+STCubeMX+generated+project.

Here is how to do it:

  1. Create a project catalog, e.g. D:\Projects\STM32.
  2. Open CubeMX and open the menu Project > Settings…
  3. Enter a project name (e.g. “STM32_proj”).
  4. Change project location to the previously created catalog (e.g. D:\Projects\STM32).
  5. Change the Toolchain / IDE to SW4STM32
  6. If you have a previously started project, these fields are not editable. Select “Save Project As…” to be able to edit the fields.
    CubeMX settings
    CubeMX settings
  7. Set up all the pins and peripherals in CubeMX and generate the code (Project > Generate Code).
  8. Open SW4STM32 (e.g. by double clicking on C:\Ac6\SystemWorkbench\eclipse.exe ).
  9. Select D:\Projects\STM32 as workspace.
  10. File > Import… > General > Existing Projects into Workspace > NextCubeMXimport
  11. Browse for D:\Projects\STM32 as root directory. The project STM32_proj should be detected and selected.
  12. Do NOT check the option “Copy projects into workspace”.
  13. Click Finish.

Unfortunately, the project did not compile for me even after these maneuvers. I found the solution at http://www.openstm32.org/tiki-view_faq.php?faqId=4#q21:

The trick is to tell SW4STM32 to not parse files that are not used by the project. This is how to do that:

  1. Select Project > Properties > C/C++ General > Indexer
  2. Check “Enable project specific settings”
  3. Uncheck “Index unused headers”.

EclipseIndexUnused

After this fix the code compiled without errors!

Getting to blinky

To quickly test that I could get all the way to code executing on the processor I added a simple LED-blinking  routine inside the infinite while loop in the CubeMX code (I had LEDs on PA15 and PA7):

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
      HAL_Delay(200);
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
      HAL_Delay(200);
  }
  /* USER CODE END 3 */

“Project > Build All” generated a .bin file in the Debug catalog under the project folder. I configured my ST-Link for talking to an external board and connected it to my target board.

ST-Link of a Nucleo board connected to the target board.
ST-Link of a Nucleo board connected to the target board.

Then I connected both boards via USB cables to the computer and dragged the .bin file to the “NODE_L053R8” drive that the ST-Link appears as. The programming worked and the LEDs started blinking!

PCB manufacturing hitch

The PCB I mentioned in the previous post was rejected by the Chinese manufacturer I sent it to since it contained several sub-boards and they wanted (a lot of) extra money for that. This is what the board looked like:

Initial PCB design
Initial PCB design

The comment I got was:

“After checked, we found there are 10 separated sub-boards in your Gerber file, it means you should pay extra $81 for it. If you don’t want to pay extra money, you can design a big outline like below right picture, then we will manufacture your boards according to your big outline.”

This is the picture they sent:

Board outline suggested by manufacturer
Board outline suggested by manufacturer

The manufacturing of ten pieces of a 10 cm x 10 cm board costs $11.90 (plus shipment), so paying an extra $81 just because I used the space to fit several smaller boards did not seem reasonable to me. The suggestion of changing the outline to avoid this cost looked like a more attractive solution, but the square outline suggested would mean I would have a rather painful depanelization to perform, so it did not look ideal.

I checked several other Chinese PCB manufacturing sites (a reasonable list can be found at the EEVblog) but all had these odd and relatively high extra fees for placing several designs within the available area. I wonder why they all have the same rules?

So what I ended up trying was to change the panelization such that it was somewhat less obvious, but with an outline that would still help me depanelize the individual boards. I removed the internal milling and the mouse bites. Then I changed the total outline to meander around larger parts of the outline of several of the smaller boards:

Modified PCB panel
Modified PCB panel

This apparently was acceptable since I got the following response:

Yes, this Gerber file is acceptable to us. We will manufacture your boards according to your new Gerber file.
About the separated sub-boards, you can refer to below requirement.

If the milling part more than 1/3, it will be counted as the separated sub boards, because it is more difficult than normal single board.

For example, 10cm length boards:
the milling length is 3cm or less, no separated sub-board.
the milling length is 3.3cm or more, separated sub-board.

So it seems like as long as one stays away from having more narrow necks than 2/3 of the width of the  board, one will avoid the extra cost. I actually do not think I quite obeyed this rule in the modified version of the board, but apparently it was accepted, so either they are not very strict, or the rules they apply are more complicated than what they say.