Showing posts with label Microchip. Show all posts
Showing posts with label Microchip. Show all posts

Sunday, 30 May 2021

Repairing the PICkit 2

 

Microchip PICkit 2 Programmer

My PICkit 2 failed:

$./pk2cmd -PPIC16F1705 -GC
Read successfully.
Configuration Memory
0000 0000
VPP Error detected. Check target for proper connectivity.

PICkit 2s are not expensive, more so the China clones now available online. Neither is its successor the PICkit 3, so I could easily have thrown it away. But it came with a great manual, complete with source code and  schematics which is uncommon. Plus the original PICkit 2 is getting hard to find these days and PICkit 3 might have issues supporting some legacy CPUs. In any case I could repurpose it: not only it is a USB device, it has a ready-made connector with 2 IO ports and a nifty 12V-0V pin. 

A VPP error is probably to do with the MCLR pin:

Pickit2 JTAG Connector              Function
        Pin 1                                     MCLR/Vpp 
        Pin 2                                     Vdd 
        Pin 3                                     Gnd
        Pin 4                                     Data 
        Pin 5                                     Clk
        Pin 6                                     N/C

6-way header


To check MCLR(pin 1) I just stuck a 6-pin header into the PICkit 2 connector and measured it with respect to Pin 3 (Gnd). It helps to make a little bash script:

$cat ./testpickit2
for i in {1..5..1} 
do 
  sleep 5
  ./pk2cmd -PPIC16F1705 -GC
done

MCLR (or Vpp) schematic diagram 


The multimeter measures MCLR at 0.15V. A sanity check with a good PICkit 2 showed this goes well up to 12V. The schematic shows an ingenious DC boost converter, using the CPU pin Vpp_Pump to periodically short the inductor L1 to ground. There is even Vpp_FEEDBACK pin to regulate its output. Two additional CPU pins, Vpp_ON and MCLR_TGT are used to switch the resulting regulated high voltage to pin 1 of the JTAG connector (ie the programming port).

I pried open the plastic case and the repair job just became a lot simpler. L1 the 680uH surface-mounted inductor fell off the PCB!



Detached inductor L1. The original position is circled in red

This happens quite a bit with surface-mounted components, particularly when subjected to mechanical stress. The inductor is among the tallest component and would have been compressed by my fingers through the thin plastic case.

680uH Inductor. Note the plastic former is plated at the ends and the inductor wire is then soldered on.

The plastic, metal-plated lead has snapped off one end. I thought it would be a slam-dunk to solder the unbroken end back on the PCB and solder the broken wire directly to the PCB. Boy I was wrong: the wire was so thin it was hardly visible under high magnification. Worse, when I stripped the enamel insulation using my soldering iron, this made the wire brittle and it eventually broke off.  

New inductor (bottom left) is larger than the original


A new 680uH inductor, 74404054681 INDUCTOR, 680UH, 0.25A, 20%, SEMI-SHLD from element14 cost RM5 (USD1). I chose it to match the leads pitch of 4mm; the other dimensions were uncomfortably larger than the original but this was the only part with a reasonably sane delivery date. I was concerned it might be too tall and prevent the plastic case from snapping shut.
Working PICkit 2


Soldering was a little tight: you need to solder the right-hand lead first and slide it right to make room for the iron tip at the left lead. But there was a happy ending: the case snapped shut and the PICKit 2 worked.
     

Sunday, 23 May 2021

I love cheap thrills: WiFi OTA for Microchip PICs

 

Cheap Thrills - Sia


"Come on, come on, turn the radio on
It's Friday night, and it won't be long
Gotta do my hair, put my make-up on
It's Friday night, and it won't be long
'Til I hit the dance floor, hit the dance floor
I got all I need
No, I ain't got cash, I ain't got cash
But I got you, baby
Baby, I don't need dollar bills to have fun tonight
(I love cheap thrills)" - 
Sia, Cheap Thrills

Firmware Over The Air programming (OTA) is all the rage with Internet of Things (IoT) devices. Ongoing privacy and security issues make it almost mandatory that they be upgradeable after installation. That usually means OTA upgrades using a smartphone App or a desktop browser.

For a hobbyist, or just plain fast and cheap development, few systems beat the ESP8266-based IoT OTA, ArduinoOTA. The ESP8266 has a few flaws. It is difficult to operate on small batteries: sleep mode still requires milliamps and while using WiFi it can surge to 100mA. Also, executing the WiFi stack takes priority and this sometimes causes interrupt service routines to have unpredictable delays. Most applications are OK with this, unless your code is time-critical like trying to a dimmer triac while connected to WiFi.

Microchip CPUs in particular shine at low-cost, low-power performance and raw horsepower. But their WiFi OTA solutions tend towards the later, more expensive models. Wouldn't it be great if we can have OTA for the Microchip CPU, say a PIC16F84 or even a PIC16F1705 if you want to roll C code? In particular the latter has a mouth-watering dedicated zero-crossing detect (ZCD) interrupt which would be very handy for a flicker-free dimmer or a heavy-duty switching of inductive loads.

It turns out this can be done. We build an ESP8266 into a Microchip PIC system and use the former's WiFi capability to program the PIC. WithArduinoOTA, both the ESP8266 and PIC have OTA. Microchip's recommendation is to use a bootloader, ie reserve dedicated program space in the PIC for  bootloader so that it can be programmed via its serial port. This possible for the PIC161705 but would would be a very tight squeeze for the PIC16F84 - the low-end PICs are usually short on memory. In addition the bootloader would be unable to change certain startup configuration bits.

PICkit 2 programmer (left) connected to a target system via its JTAG port


There is another way to do serial programming for a Microchip PIC: most of them support In-Circuit Serial Programming or ICSP. This is the same method a Microchip Programmer like the PICkit 2 uses. An ESP8266 program speaking ICSP to the PIC will be able to program it without resorting to a bootloader. It turns out this has already been done: mengstr's esppic hackaday project. His source code is in github.

This post really has little to add to mengstr's work, except maybe a little documentation on how to get it up and running, and with luck add some support for the PIC16F84 or even the venerable PIC16F57.

Schematic for target CPU board

The ESP-12E to JTAG programming connector pinout is:

               Pickit2                                 ESP-12E

            Pin 1     MCLR/Vpp               D0/GPIO16

            Pin 2     Vdd                           3V3

            Pin 3     Gnd                           Gnd

            Pin 4     Dat                            D1/GPIO5

            Pin 5     Clk                            D2/GPIO4

            Pin 6     N/C

This way the PIC16F1705 development board can be programmed from both the PICkit 2 and the ESP-12E. The JTAG port also lets you run the target system directly from the PICkit 2. Not having to unplug the target system and hooking it up to another power source greatly speeds up the development cycle.

PICkit 2 might need an updated PK2DeviceFile.dat file for the PIC16F1705. In my case I use pk2cmd with Linux. pk2cmd needs to be updated to work with Gerhard Bertelsmann's version of pk2cmd It is tucked away in a gigantic 300MB misc repository, so I copied it here for your convenience. To compile, simply:

$make linux

To test, plug the target CPU board into the PICkit 2 JTAG port.
$./pk2cmd -PPIC16F1705 -GC
Read successfully.

Configuration Memory

3EFF  3F87

Operation Succeeded

To program,

$./pk2cmd -PPIC16F1705 -Fblink_led.hex -M
PICkit 2 Program Report
18-5-2021, 9:38:13
Device Type: PIC16F1705

Program Succeeded.

Operation Succeeded

To run,

$./pk2cmd -PPIC16F1705 -GC -T -R

To stop running (in order to unplug)

$./pk2cmd -PPIC16F1705 -GC

To compile my program I used sdcc sample code from Diego Herranz. For Debian sdcc installation is simply:
#apt-get update
#apt-get sdcc

For Slackware it is a little bit more involved. We need the pic14-port ad pic16-port so first get the gputils source code.
$./configure
$make clean
$make
$su -c "make install"

Next get the sdcc source code from sourceforge

Next, untar it:
$tar -xvjf sdcc-src-3.9.0.tar.bz2

Then build it:
$./configure
$make -j 10
$su -c "make install"

Here is Diego Herranz's pic14/1.blink_led/blink_led.c modified slightly for the PIC16F1705:

// Copyright (C) 2014 Diego Herranz

#define NO_BIT_DEFINES
#include <pic14regs.h>
#include <stdint.h> 

// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN),
// disable watchdog,
// and disable low voltage programming.
// The rest of fuses are left as default.
//__code uint16_t __at (_CONFIG1) __configword = _INTRC_OSC_NOCLKOUT & _WDTE_OFF & _LVP_OFF;
__code uint16_t __at (_CONFIG1) __configword = _FOSC_INTOSC & _WDTE_OFF & _LVP_OFF;

#define LED_PORT PORTCbits.RC0
#define LED_TRIS TRISCbits.TRISC0

// Uncalibrated delay, just waits a number of for-loop iterations
void delay(uint16_t iterations)
{
        uint16_t i;
        for (i = 0; i < iterations; i++) {
                // Prevent this loop from being optimized away.
                __asm nop __endasm;
        }
}

void main(void)
{
        LED_TRIS = 0; // Pin as output
        LED_PORT = 0; // LED off

        while (1) {
                LED_PORT = 1; // LED On
                //delay(30000); // ~500ms @ 4MHz
                delay(5000); // ~500ms @ 4MHz
                LED_PORT = 0; // LED Off
                //delay(30000); // ~500ms @ 4MHz
                delay(5000); // ~500ms @ 4MHz
        }
}

To compile it:
$sdcc -mpic14 -p16f1705 --use-non-free blink_led.c

If you do not want the hassle of compiling it, here is the hex file:

:020000040000FA
:10000000000080310328DE30FB008030FC008030AF
:100010008031832080312C00A1007C08A000E030DA
:10002000A2008030A3002C002008A4002108A50015
:10003000FF30A007031CA10324082504031980280E
:1000400004302207A400A501A50D2308A507240854
:10005000FB002508FC0080308031832080312C009B
:10006000A7007C08A6002208FB002308FC008030C3
:100070008031832080312C00A900A5007C08A800D5
:10008000A40002302207A400A501A50D2308A5079E
:100090002408FB002508FC0080308031832080315B
:1000A0002C00A500AB007C08A400AA002C002608A8
:1000B000AA002708AB00FF30A607031CA7032A08E5
:1000C0002B0403197A282808FB002908FC0080303B
:1000D0008031A02080312C00AA002408840025084B
:1000E00085002A088000A80A0319A90AA40A03198E
:1000F000A50A562806302C00A2070318A30A1328C5
:100100008031B2280800003A03198B28803A03197D
:100110009328FC0100347B0884007C0885001200D1
:10012000FC00000808008031AD20FA00FB0FFC0342
:10013000FC0A8031AD20F9007A08FC00790808003B
:10014000003A0319A728803A0319AD2800347B0828
:1001500084007C088500000808007C088A007B0871
:100160008200080021000E1020000E1020000E1446
:100170008830FC0013308031C820803120000E1000
:100180008830FC0013308031C8208031B628080048
:100190002C00AD007C08AC00AE01AF012C002D0896
:1001A0002F02031D02322C082E020318DD28000046
:1001B0002C00AE0A0319AF0ACE280800013400341F
:0E01C000E634003430340634013400340034A8
:020000040001F9
:02000E00E41FED
:00000001FF

Next we move on to the Arduino IDE to compile mengstr's esppic code over at his github repository. The ESP8266 code is in https://github.com/mengstr/esppic/tree/master/esppic, and you need to set the compile settings for NodeMCU ESP-12E, CPU speed 80MHz. 

You will also probably need to pull in a library from Websockets library from here. In addition you will need to put in the same local Arduino code directory, a sub-directory named data and fill it with the files from mengstr's https://github.com/mengstr/esppic/tree/master/assets. They are necessary for the webserver code for the ESP8266. 

In the Arduino IDE, go to Tools->ESP8266 Data Upload and program the SPIFFS data/ files. Next, program the ESP8266 NodeMCU via the USB port. It comes up as a WiFi Access Point, so connect to it, maybe with your smartphone or laptop. With a browser, connect to http://192.168.4.1 and type in your WiFi SSID and password.

NodeMCU ESP-12E wired to JTAG port of PIC16F1705 target CPU board


Now power off and connect it to the JTAG port of the PIC16F1705 target board. Make sure in Arduino IDE you have the Debug Monitor active at the USB serial port, as it will come up with the IP address as it starts up. Say it is 12.34.56.78. With a browser, connect to http://12.34.56.78.

You should see something like this in the Debug Monitor :

Connecting to wifi using default info
..
Successfully connected. IP=12.34.56.78
handleFileRead(/)
/index.html (0 bytes) Open:53 Stream:1 Close:0
handleFileRead(/)

Screenshot of programming webpage


You should first try reading the CONFIG1 and CONFIG2 registers. In my case I had trouble getting a  brand-new blank PIC16F1705 to work; I had to first program it with the PICkit 2. If it works, the browser should show:

MEMORY DUMP
DEV ID : 3055
DEV REV: 2003
CONFIG1: 1fe4 (0001 1111 1110 0100)
CONFIG2: 3fff (0011 1111 1111 1111)
USER ID: 3fff 3fff 3fff 3fff

Followed by a memory dump, something like:

0000: 0000 3180 2803 30DE 00FB 3080 00FC 3080 3180 2083 3180 002C 00A1 087C 00A0 30E0
0010: 00A2 3080 00A3 002C 0820 00A4 0821 00A5 30FF 07A0 1C03 03A1 0824 0425 1903 2880
0020: 3004 0722 00A4 01A5 0DA5 0823 07A5 0824 00FB 0825 00FC 3080 3180 2083 3180 002C
...

To program use a browser, or navigator or Konqueror to drag the hex file over to the programming icon. I could not get mine to work with Google Chrome, but Konqueror or Firefox works for me.

Sometimes esppic locks up during a memory dump or programming; I find it best to simply power-cycle it and start afresh. For some reason I could not get it to recover from an error condition. Notice the PIC16F1705's programming datasheet recommends using 5V while programming and we are using 3.3V so maybe this caused the flakiness. You can at a pinch wire it to the ESP-12E's 5V, but I would not recommend long-term usage like that as the ESP8266 datasheet says it is a 3.3V device and mught get over-stressed. It would be instructive to try the PIC16LF1705, which is an explicitly low-voltage version.

There you have it, WiFi OTA for the Microchip PIC16F1705. I don't need dollar bills to have fun tonight. I love cheap thrills. 

Happy Trails.

Wednesday, 12 May 2021

Development System for the ancient Microchip PIC16F57 CPU

 

Microchip PICkit 2 Programmer with target system

The Microchip PIC16F57 is an ancient CPU, long superceded and only grudgingly sold by Microchip Inc. Indeed there is currently a 2-month wait for them. It has a tiny 2K word program memory and a microscopic 72 bytes RAM. Too small to use with C, To program it, you would need assembly language. Why would I want to waste time on something like that? 

I have a remote gate opener ('autogate') which I tinker with unmercifully. It is also underneath an powerhead mains power pole which seems to get struck by lightning a few times a year, so over the years I accumulated a stack of dead S-1 controller boards which I usually repair and reuse. Except for those few which had dead CPUs.

S-1 Autogate Controller Board

Now they are cheap enough: RM100 (USD25) will buy you one online. But repairing these last boards meant replacing the CPU, which meant writing the program for it. After some effort, I noticed that the CPU footprint is an exact match for the Microchip PIC16F57, and I even have one in my CPU tray.

Writing the program also means I can upgrade the CPU to a newer one, and maybe add WiFi connectivity as well. And since the Chinese can sell me the board cheaper than I can make it, it does not make sense to make my own PCB. To upgrade it I would first have to replicate its functions, and that means writing the program from scratch.

But before I can even do that I have to find an Assembler, device programmer and build a little target system (PIC16F57 CPU board) just to make sure the toolchain works.

Microchip's MPLAB Version 8.33 (an equally ancient version running on Microsoft Windows XP) works for me. It comes with the MPASM assembler which happened to support the PIC16F57. You can try your luck with the latest and greatest MPLAB, but if it does not work out, you can get Version 8.33 from the Microchip MPLAB archive. I run a Windows XP image from a Qemu-KVM virtual machine and use pk2cmd with my PICkit 2 programmer, but you will probably be quicker off the mark with a Windows XP laptop.

The next thing you need is a little PIC16F57 (ie target) board just to accept the PICkit 2 connector and also run a small test program.  

PIC16F57 target system


Then you need the test program which you feed into your MPLAB assembler and produce the hex file the PICkit 2 needs to program the CPU. Usually you can find such sample programs in the great wide Internet but for some reason, not for the PIC16F57. You can find the schematics, hex file and source code here in my github repository.

To program the PIC16F57 I use:

$./pk2cmd -PPIC16F57 -Fledblink.hex -M

To run it I use:

$./pk2cmd -PPIC16F57 -GC -T -R

Some notes of caution: my experience is a Microchip CPU in a new target system can be hard to start. The combination of your choice of oscillator affects the Power-on Reset Timer delay. The MCLR reset circuit also changes things. You also need to sort out you Reset and Watchdog Timer vectors without which you program will not start. Once you get past that it is usually plain sailing. Using a Microchip Development Kit makes real sense here, but they have long since abandoned the PIC16F57. Also having a known good toy program helps when you are trying to start the CPU.

Despite having only 2K the PIC16F57's memory is also segmented. The simplest way is to ensure the program sits within page zero 000-1FF. This is because subroutines calls only work within page 0. You can next just 2 levels of subroutines.

Lastly the digital output pins are set and cleared (ie BSF and BCF) using a Read-Modify-Write mechanism. This means the CPU does not keep a record (ie a register) of your IO bits. It also accesses IO 8 bits at a time and if it executes a write, it will first read the whole byte from the external circuits, modify the read data and writes back the 8 bits. This can have unexpected effects if you are not running within the electrical operating limits (ie driving too much current into an LED). Also a CPU IO write followed immediately by a read may execute too fast for the external circuit.

The RC system clock circuit is a little hard to time accurately because of its inherent inaccuracy and component tolerances. If your LED does not blink, you might need to adjust the delay intervals. If that fails, seek to dim the LED rather than blink it.

This is a hard-core RISC instruction set, running in a Harvard Architecture (ie program and data busses are separate). There is usually no substitute to reading every single word in the datasheet.

If this is your first time with assembly language, congratulations. You have talked to a CPU in its own language, mano a silicona, and it understood you. 

Good Luck, and Happy Trails.