Diagnosing and fixing Faulty Electronics

Diagnosing and fixing Faulty Electronics will show how to diagnose and repair electronics using parts you possibly have in your collection.

Hey listen…, electronic devices have become an integral part of our lives, providing or enhancing education, safety, medical care and entertainment on the go. However, like any device, it can break or develop faults over time. Although the new trend dictates throwing broken electronics in the trash, I will walk you through the process I used to diagnose a faulty multi-source audio player and what I did to fix it.

Identify the Problem

The first step in diagnosing and repairing any faulty electronic device is to understand and identify the problem. There are thousands of ways something can fail, for example, if your device has no power. That is, the device doesn’t turn on at all, there is no light, no sound no movement no nothing that indicates that it’s operating. It could be due to a dead battery or faulty charger, a faulty power button, or a problem with the internal circuitry.

I could write an entire post just to list some of the odd ways a device can fail but in this post, I will focus on a particular device with a particular problem. You should always think simply and if you cannot find the problem, you should think about more complicated things.

The Device

The device I worked on was a small and cheapy, battery-powered FM radio/audio player that could read audio files, a.k.a. mp3, from SDCards and USB flash drives and also had an auxiliary input jack, which is neat!

Front view. Main panel and speakers.
Front view. Main panel and speakers
Back view with analog volume control power switch and audio jacks
Back view with analog volume control power switch and audio jacks

I don’t know why but many cheap Chinese products have to have something odd or fake in them. This one had a fake speaker. One of the top speakers was fake and it was hard to tell which one was the fake one. I know now because I opened the device and saw it guts!

Top speakers. One is fake =]
Top speakers. One is fake =]

Tools and Materials

Before you start diagnosing and repairing electronics, make sure you have the following tools and materials:

  • A clean workspace with good lighting
  • Screwdrivers (usually Phillips and sometimes Torx)
  • Multimeter (could be cheap as a flock but it must be a reliable one)
  • Soldering iron (I like the temperature-controllable ones but could be the simplest depending on the type of electronics)
  • Solder, of course (flux is good to have)
  • Oscilloscope (someday you’ll need a simple one)
  • Small plastic prying tools (I use cheap guitar picks)

Diagnose the problem

The problem with my little patient was that one of the two speakers (the real ones =]) suddenly stopped to play sounds. This scenario was always present, no matter if the audio source was FM radio, USB flash driver or the SDCard. Also, I tried to mess around with the buttons or the volume pot and the problem was still there.

Now is a good time to ask you to read the disclaimer page =].

Disassembly

I removed the back panel (that one with audio input and output jack) and discovered that there were two boards, one for the radio tuning, card reader, read buttons, drive the display, and all that jazz and another board with the audio amp. My attention was focused on the second board because I started to track the issue from de output (the speakers) to the input (probably a microcontroller).

Audio amplifier board - Top view
Audio amplifier board – Top view
Audio amplifier board - Bottom view
Audio amplifier board – Bottom view

Multimeter Probing

First of all, I used the multimeter to measure the speakers not connected to the board. Both were good, with 4 ohms each. Then I measured spk 1 and spk 2, which are the speaker connectors, in reference to ground and I got around 2v on both! That was a surprise. I was expecting one of them to be shorted to ground. Before checking the voltages at spk 1 and spk 2 I was guessing that one of the chips went faulty, and I expected most of its pins with no voltage but that was not the case.

As the first observations were not conclusive, I searched for the integrated circuit datasheet. The chip marking was CM8600A, a 3-watt audio amplifier with a shutdown pin.

Chip pinout oriented like on the board
Chip pinout oriented like on the board

For this particular circuit, a datasheet is not really required because we can assume, with a basic understanding of audio amplifiers, that the chip must have at least one pin for input and another pin for output. In this way, one could follow the trace from the speaker connector to the chip, maybe expecting some passive component in between, and find the output pin.

Example circuit from the datasheet.
Example circuit from the datasheet

The pinout figure and this example circuit, both extracted from the datasheet, show what we’ve got at the board.

After some more time probing around with the multimeter, I noticed that pin 4 of one of the chips was practically stable at 2v while the same pin on the other chip was oscillating a bit. Besides that, both chips seemed to be good.

Oscilloscope Probing

At this point, I was just guessing the faulty IC again, based on a little difference between the reading on pin 4. So, I decided to use the oscilloscope and probe the input and output pins. As expected, I got some messy waveforms because I was playing some random music.

To get a better idea of the waveforms, I used ffmpeg to create a stereo mp3 file with a particular tone frequency on each channel. For the left channel, I chose 550Hz and for the right channel 440Hz.

ffmpeg -f lavfi -i "sine=frequency=550:sample_rate=48000:duration=300" -f lavfi -i "sine=frequency=440:sample_rate=48000:duration=300" -filter_complex "[0:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=mono,volume=4[a1];[1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=mono,volume=4[a2];[a1][a2]amerge" -y L550hz_R440hz.mp3

I’m using Linux and I can use ffmpeg it from a simple terminal emulator. If you are using Windows (without the Linux subsystem), I’m really sorry for you.

I loaded the generated mp3 file on an SDCard, just because I could, and started to probe again. This time I got a clear view of the problem. One of the chips, the one with the quiet pin 4, was dead. The input signal was good but there was no output. Moreover, I was able to find out that the volume control was not working properly!

Here are some pictures of the waveforms. I do not have the waveform of the dead chip because it was a flat line around the 2v.

Left channel probing before volume control
Left channel probing before the volume control

This is the waveform of the left channel, probing the pin marked as “probe point 2” at the bottom left of the audio amp board.

Right channel probing before the volume control

This is the waveform of the right channel, probing the pin marked as “probe point 1” at the bottom left of the audio amp board.

Right channel probing after the volume control

This is the waveform of the right channel, probing the pin marked as “probe point 3” after the input capacitor. There was a little noise but I couldn’t hear it from the speaker.

Solution

The simplest solution to this kind of problem is to replace the faulty component. Unfortunately, the local electronic component supplier did not have this chip or a possible replacement. Also, I would need two of these chips because this device had a twin brother with the same problem. So I decided to transplant the functional chip to the brother and for this guy, I chose a more invasive procedure. I built an extension board with another audio amplifier.

Extension audio amp board - Top view
Extension audio amp board – Top view

I used a DIP dual power amp, the TDA2822M that I had in my parts stash. It’s a good choice for this kind of project because is a low-supply voltage chip, it can operate at voltages down to 1.8v, ideal for battery-powered devices like this one.

Example of circuit application extracted from the TDA2822M datasheet
Example of circuit application extracted from the TDA2822M datasheet

I used this example circuit provided by the TDA2822M datasheet for the extension board. Of course, I changed some passive components like the output capacitors and input resistors to fit my needs (all empirically =]). Also, I had to remove a pair of resistors (output) and change a pair of capacitors (input) from the original board.

Extension audio amp board - Bottom view
Extension audio amp board – Bottom view

That was a pretty small perfboard to work on. The soldering was made with a pair of tweezers and a fine soldering iron tip. Fortunately, all went well and the amp was working nicely.

Extension audio amp board - Wiring to the main amp board
Extension audio amp board – Wiring to the main amp board

Is worth mentioning that the wiring should be as small as it could be to avoid interference, particularly at the input lines.

I built the same circuit on a small breadboard using long wires for the power supply, inputs and outputs. The breadboarded circuit tricked me for a while because it was extremely noisy with a lot of hum, I even thought the chip was defective. A decoupling capacitor is mandatory here!

Conclusion

Diagnosing and repairing any faulty electronics can be rewarding. Not only by resurrecting a piece of dead equipment and reducing e-waste but also because we can learn a bunch of new stuff. By identifying the problem, gathering the necessary tools, and finding suitable replacement parts or adapting them as needed, you can bring devices back to life.

Warning note here: Always exercise caution and prioritize safety, especially when working with electronics. If you don’t have the necessary skills yet, go to a repair shop to ensure a successful repair.

ATtiny85 Gamepad

Build your own gamepad from literally scratch using the ATtiny85 microcontroller, the V-USB driver and a lot of creativity.

Hey listen… this project is from 2020, the pandemic boom. From when people were spreading COVID-19 all over the world.

I’ll show how I built an HID gamepad using the Atmel ATtiny85 microcontroller, shift registers, some passive components and firmware based on the V-USB library.

The ATtiny85 is a small and powerful microcontroller that, despite its low pin count, is perfect for this kind of project.


HID Basics

HID stands for Human Interface Device. These USB devices are used to communicate to the computer using drivers shipped with the operating system, so you don’t need to install additional drivers. Some common examples of HID devices include keyboards, mice and game controllers. HID devices use the USB protocol to communicate with the computer and the devices are “configured” by the HID report descriptor.

The HID device descriptor is used to inform the host device (mostly your desktop or laptop but can be any device that can operate in USB “host mode”), how data sent (reports) by the device will be interpreted. It is a byte array defined by you in your program, configured according to the needs of your device. You can find great information at the usb.org website. Also on the page, you can find a tool that helps to create the device descriptor of your HID device. The device descriptor configures things like the device class, how many devices (yes, you can use just one USB device and report multiple gamepads =]) and how big are your data packages. For example, the descriptor of my gamepad is configured with 8 buttons and 2 axis but it could be configured with more buttons or axis by changing the descriptor byte array.


Circuit design

The hardware setup for this project is relatively simple. We will need an ATtiny85 microcontroller, a USB connector, two shift registers and some simple components.

The ATtiny85 (datasheet) is a great microcontroller but has a few pins, two for power and ground, one for reset and five multi-function pins. To extend its I/O pins to my needs, I used two shift registers connected in series (daisy chained). A shift register takes a clocked serial input and latches its output pins to a low state (ground), high state (5 volts for this project) and sometimes (depending on the shift register) high impedance state (disconnect the pin). For this project, I used the shift register 74HC595 (datasheet).

Then I defined the microcontroller pins for the following tasks:

  • Driver the shift registers (three pins: data, clock and latch)
  • Read the state of each button and axis (one pin: state sense)
  • USB communication (two pins: D+ and D-)

To drive the 74HC595 we need to LATCH a CLOCKED serial DATA generated by the microcontroller, which means that at least three pins of the five available I/O pins will be used. We could program the RESET pin to work as an ordinary I/O pin and get all the six pins we need, but after that, the RESET pin could not be used to program the microcontroller. This is not a good idea in the early stages development of a circuit. Instead, we will use the CLOCK line to also drive an NPN transistor and charge a capacitor. This capacitor holds the shift registers LATCH pin in a high state for enough time, so the shift registers can activate their output pins.

The following image shows the LATCH driver.

Latch circuit
Latch driver

I selected the capacitor value by trial and error. For my circuit, a 100nF ceramic capacitor was good enough.

My gamepad has 8 buttons and 2 axes (two pins for the X-axis and two pins for the Y-axis). To read all the possible states (pressed or not pressed) for all these inputs, at least 12 pins are needed out of the 16 pins provided by the two 74HC595 connected in series. Each output has a diode to prevent shadowed reads when multiple buttons are pressed at the same time.

Shift register circuit
Daisy chained shift registers

Shifting one bit thru the shift registers will activate each button individually and the microcontroller will read thru the SIGNAL line for any button press.

The SIGNAL line must have a pull-down resistor otherwise parasitic capacitance may cause wrong reads or activate permanently all buttons and axis at the same time. I used a 1k resistor for the pull-down, but values between 1k and 4k7 are acceptable.

Signal line circuit
SIGNAL pull-down resistor

According to the V-USB library documentation, we must use an interruption pin for the D- line. At this point, we can define all the microcontroller physical pins for each function as shown below.

Microcontroller pins and their roles/functions

The V-USB library documentation provides some examples of circuits to the USB data lines, as shown in the next figure. It must follow the USB standards otherwise the device may not function as expected.

USB connection circuit

I used three of the free pins of the shift registers to drive an RGB LED.

RGB LED circuit

I build the circuit on a breadboard and started to write the firmware for it.

Gamepad circuit on a breadboard

Firmware development

Most of the hard work of this firmware is done by the V-USB library (lucky me!) which is also the most time-consuming for the microcontroller itself. The firmware can be divided into five parts:

  • V-USB configuration
  • HID report descriptor definition
  • Shift register driver
  • LED driver
  • Main loop

V-USB configuration

The V-USB configuration is made easy because of the usbconfig.h header is well documented. We just follow the comment instructions on each define line according to our needs. Here are some important configurations for this project:

#define USB_CFG_IOPORTNAME      B

#define USB_CFG_DMINUS_BIT      3

#define USB_CFG_DPLUS_BIT       4

#define USB_INTR_CFG            PCMSK
#define USB_INTR_CFG_SET        (1 << USB_CFG_DPLUS_BIT)
#define USB_INTR_CFG_CLR        0
#define USB_INTR_ENABLE         GIMSK
#define USB_INTR_ENABLE_BIT     PCIE
#define USB_INTR_PENDING        GIFR
#define USB_INTR_PENDING_BIT    PCIF
#define USB_INTR_VECTOR         PCINT0_vect

#define  USB_CFG_VENDOR_ID      0xc0, 0x16
#define  USB_CFG_DEVICE_ID      0xdc, 0x27

#define USB_CFG_VENDOR_NAME     'A', 'R', 'E', 'N', 'A', '6', '4'
#define USB_CFG_VENDOR_NAME_LEN 7

#define USB_CFG_DEVICE_NAME     'F', 'i', 'n', 'g', 'e', 'r', 'G', 'r', 'i', 'n','d', 'e', 'r'
#define USB_CFG_DEVICE_NAME_LEN 13

You should put the name of your gamepad in USB_CFG_DEVICE_NAME. It is the name that will show up on the Windows tray when you plug in your gamepad. Mine is FingerGrinder.

HID report descriptor definition

I used the “HID usage table” document which can be found here to create my descriptor. This file gets updates from time to time. You can find the update here. Also, you can use the “HID descriptor tool” to build the device descriptor.

0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
0x09, 0x05,                    // USAGE (Game Pad)
0xa1, 0x01,                    // COLLECTION (Application)
0x09, 0x01,                    //   USAGE (Pointer)
0xa1, 0x00,                    //   COLLECTION (Physical)
0x09, 0x30,                    //     USAGE (X)
0x09, 0x31,                    //     USAGE (Y)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x02,                    //   REPORT_COUNT (2)
0x81, 0x02,                    //   INPUT (Data, Var, Abs)
0xc0,                          // END_COLLECTION
0x05, 0x09,                    // USAGE_PAGE (Button)
0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
0x29, 0x08,                    //   USAGE_MAXIMUM (Button 8)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x75, 0x01,                    // REPORT_SIZE (1)
0x95, 0x08,                    // REPORT_COUNT (8)
0x81, 0x02,                    // INPUT (Data, Var, Abs)
0xc0                           // END_COLLECTION

Shift register driver

The ATtiny85 has a USI (Universal Serial Interface) which can be configured to operate in SPI mode. We will use this interface to generate the CLOCK signal and send the serial DATA to the shift registers.

The latch part of this serial driver has to be put into the main loop because we have to latch the signal before trying to read each button.

SPI_PORT |= (1 << USCK_PIN); //enable clock (and charge latch cap)
_delay_us(1); //waiting for charge
SPI_PORT &= ~(1 << USCK_PIN); //disable clock

If you do not understand how to expand the microcontroller I/O with shift registers or read the state of buttons using a single input pin, I suggest you watch this great video.

LED driver

The LED driver was based on a simple and nice code that you can find at Ɓukasz Podkalicki

Main loop

At the main loop, we poll the USB and “wait” to send the data relative to the current state of the gamepad, if any button is pressed. It is important to sort/order the data according to the descriptor that was defined earlier.

usbPoll();
if(usbInterruptIsReady()) { //send data when the usb is ready to receive
	if(has_changed) { //and when any change occurred
		buildReport(); //build the report according descriptor
		has_changed = 0; //clean change flag
	}
	usbSetInterrupt(report_buffer, sizeof(report_buffer)); //send data
}

After that, we have a loop to read all buttons and mark if it was pressed or not.

while(!(mask & 0x1000)) {
	// placing bit on right place to shift into shifters
	b2 = (uchar)((mask & 0xff00) >> 8);
	b1 = (uchar)(mask & 0x00ff);
	b2 |= (rgb_led_state() << 5);

	SPI_PORT |= (1 << USCK_PIN); //enable clock (and charge latch cap)
	_delay_us(1); //waiting for charge
	SPI_PORT &= ~(1 << USCK_PIN); //disable clock

	// loading serial data (shifting bits to the shift register)
	simple_spi_send(b2);
	simple_spi_send(b1);

	_delay_us(666); //waiting for button settle down (debouncing)

	if(PINB & 0x01) { //reading if the button is pressed
		signal |= mask; //add the state of each button to the buffer
	}
	mask = (mask << 1); //set the next button to be read
}

Building and flashing the firmware

To write the code I used the VSCode with C/CPP extensions. The build process is facilitated with Makefiles. Here’s an example.

# -------------- start of configurtion --------------

PROJ_NAME = firmware
DEVICE = attiny85
CLOCK = 16500000L
PROGRAMMER = usbasp

# https://www.engbedded.com/fusecalc/
FUSE_LOW = 0x62
FUSE_HIGH = 0xdd
FUSE_EXTENDED = 0xff


INCLUDES = -I/usr/lib/avr/include -I./src -I./src/usbdrv
LFLAGS =
LIBS =
CFLAGS = -std=c11 -Wl,-Map,$(PROJ_NAME).map -mmcu=$(DEVICE) -DF_CPU=$(CLOCK) $(INCLUDES)
CPPFLAGS = 

# -------------- end of configuration --------------

AVRDUDE = avrdude
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
CC = avr-gcc

H_SOURCE = $(wildcard ./src/*.h)
H_SOURCE += $(wildcard ./src/usbdrv/*.h)
C_SOURCE = $(wildcard ./src/*.c)
C_SOURCE += $(wildcard ./src/usbdrv/*.c)
S_SOURCE = $(wildcard ./src/usbdrv/*.S)
CPP_SOURCE = $(wildcard ./src/*.cpp)

OBJ = $(C_SOURCE:.c=.o) $(S_SOURCE:.cpp=.o) $(CPP_SOURCE:.cpp=.o)

RM = rm -rf

all: objFolder hex eep size

$(PROJ_NAME).elf: $(OBJ)
	@ echo 'Linking: $@'
	$(CC) $(CFLAGS) $(CPPFLAGS) $(LFLAGS) $(LIBS) $^ -o $@
	@ echo 'Finished linking: $@'
	@ echo ' '

./obj/%.o: ./src/%.c ./src/%.cpp ./src/%.h
	@ echo 'Building objects: $<'
	$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
	@ echo ' '

./obj/main.o: ./src/main.c $(H_SOURCE)
	@ echo 'Building main: $<'
	$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
	@ echo ' '

hex: $(PROJ_NAME).elf
	$(OBJCOPY) -R .eeprom -R .fuse -R .lock -R .signature -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex

eep: $(PROJ_NAME).elf
	$(OBJCOPY) -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex $(PROJ_NAME).elf $(PROJ_NAME).eep

size: $(PROJ_NAME).elf
	$(AVRSIZE) --format=avr --mcu=$(DEVICE) $(PROJ_NAME).elf

disasm: $(PROJ_NAME).elf
	$(OBJDUMP) -d $(PROJ_NAME).elf

objFolder:
	@ mkdir -p obj

clean:
	@ $(RM) ./obj/*.o ./src/*.o $(PROJ_NAME).elf $(PROJ_NAME).hex $(PROJ_NAME).eep $(PROJ_NAME).map 

test:
	$(AVRDUDE) -c $(PROGRAMMER) -p $(DEVICE) -v

flash: all
	$(AVRDUDE) -c $(PROGRAMMER) -p $(DEVICE) -U flash:w:$(PROJ_NAME).hex:i

dump:
	$(AVRDUDE) -c $(PROGRAMMER) -p $(DEVICE) -U flash:r:dump_$(shell date +'%y%m%d%H%M%S').hex:i

fuse:
	$(AVRDUDE) -c $(PROGRAMMER) -p $(DEVICE) -U lfuse:w:$(FUSE_LOW):m -U hfuse:w:$(FUSE_HIGH):m -U efuse:w:$(FUSE_EXTENDED):m	

.PHONY: all clean

# DO NOT DELETE THIS LINE -- make depend needs it

To build just type:

make clean && make

To flash the firmware I use AVRDUDE (also in the makefile). Just run this command:

make flash

The fuses were configured for this particular project. Before running make fuse read the ATtiny85 datasheet to understand its meanings.

Building the gamepad case

This task was the most time-consuming one. I do not have a laser cutter or a 3D printer so all the work was hand-made using prehistoric tools such as hand saws, files and sandpaper. The job wasn’t worse because, thank god, I have a Dremel and an electric drill.

I guessed that all the work would be done on a weekend but I was so wrong! It took almost fifteen f*#&ing days to finish the whole project. The electronics and programming were finished at the weekend, but all the structural handwork took me ten days. Most of the time was spent searching for the right part, cutting, sanding, gluing and making it all fit together.

I used a tuna can as the case, scraped plexiglass to hold the keys in place and the cover, random plastic bits like buttons (yes sir, the one used in sewing), scraped pocket calculator parts to make the key contacts and some random stuff to hold everything in place.

I ate all the tuna into this can, washed it for real, pimped my can with a nice’n shiny blue vinyl film to the outside, cut some cardboard and placed to the bottom of the can to ensure no short circuit, marked the place to drill the hole for the USB port and then finished it with a small file. In the end, I cut skinny pieces of black EVA foam and glued them to the border to make it look good!

Testing if the USB port fits well into the tuna can

Scared tuna can (eyes are markings for drilling the shoulder buttons holes and mouth is the USB port)

Assembling and hand-wiring the circuit also took some time but it was done in the weekend.

Bottom of the perfboard with my beautiful hand-wire job

The key contacts board was built using scraped plexiglass, pieces of a PCB from an old solar calculator, magnet wire and flat cable from an old floppy driver.

Key contacts board

The button holes were made with a drill and the Dremel sanding drum. I cut the D-PAD slot with the Dremel cut disk and finished it with a file.

Top view of the partially assembled gamepad

The directional control (D-PAD) was made with epoxy putty and the gamepad buttons with colored buttons.

D-PAD made of white epoxy putty

Colored buttons glued with epoxy glue to two boring white buttons.

Buttons made of buttons

The shoulder buttons and their holders were custom-made using random plexiglass scrap and bits of some retractable pens.

Custom-made shoulder button, holder and my nails in need of care

The structure is stacked together with epoxy glue, mounting posts, that are used to hold motherboards and screws.

Side view showing the circuit board, key contacts holder, cover and the mounting posts

Conclusion

The gamepad worked very well, I was able to play games that need speed and accuracy in movements, however, the D-PAD and the buttons have some gaps that could be fixed if I use more accurate methods or tools during its production. Maybe I would use epoxy resin and models for the next time.

Building a HID gamepad using the Atmel ATtiny85 microcontroller and the V-USB library is not as difficult as it seems and while challenging, the process of building something useful out of scraped materials is a very enjoyable one. I really need to buy a 3D printer and a laser cutter LOL!

Get the source: https://github.com/raffsalvetti/FingerGrinder

See ya!