Saturday, October 31, 2020

0000 0000 0100 0111

Making an old man programmer

Since the dawn of the "Pesky Padauk Programmer Project"™ (part one and part two) I have been wanting to make a version that suits my old man eyes, plus I thought it might be an opportunity to learn a bit about how this circuit (and hence how the Padauk chips) function.

I grabbed the relevant files and then tweaked the PCB to be outrageously large by comparison to the original. As always, there are mistakes - the holes for the 1N5817 diodes are too small, and the holes for the through-hole capacitors are too close together.



But the programmer loads the firmware when finished - and the next step is to make sure that it can program a Padauk chip, particularly the PFS154.

If you would like to have a tweak or two - here are the gerber files - at this stage (edit: now Aug 2022, this version DOES NOT WORK as is).

Thank you to PCBWAY for their sponsorship, support and advice. Here is the result:





Saturday, October 24, 2020

0000 0000 0100 0110

Hot Chips in an oven

No, this is not a recipe blog all of a sudden! I am exploring all options to make the pesky PADAUK FreePDK programmer project as to date my ham-fisted soldering has resulted in a melted mess rather than the expected lovely PCB goodness. To that end, I bought a cheap oven.

Temperature control is clearly fairly rudimentary on the original unit, and in fact it is possible to buy control circuitry to bake perfect chips as per the heating/cooling profiles for various solder paste formulations.


Instead (and because I'm cheap) I'm going to press into service a combination of an appropriate K-type thermocouple, plus a MAX6675 to help an AVR to interpret and plot the temperature inside the oven. I'm hoping the combination of live monitoring and mad flicking of switches might give me enough control to make the solder flow. The unknown at this stage is my ability to smear solder paste WITHOUT a stencil! What was I thinking? Oh yeah, cheap...

Firstly I hooked up the thermocouple to the MAX6675 module, loaded up example code, made a few quick modifications and ran the program to see if it worked.

/*

ATMega8A temperature probe
https://github.com/YuriiSalimov/MAX6675_Thermocouple
OneCircuit Tuesday 20 October 22:28:10 AEDT 2020
*/ #include <Thermocouple.h> #include <MAX6675_Thermocouple.h> #include <SmoothThermocouple.h> #include <TM1637Display.h> #define SCK_PIN 6 #define CS_PIN 7 #define SO_PIN 8 #define CLK 13 #define DIO 12 int temperature = 0; #define SMOOTHING_FACTOR 5 Thermocouple* thermocouple = NULL; TM1637Display display(CLK, DIO); void setup() { display.setBrightness(0x02); Thermocouple* originThermocouple = new MAX6675_Thermocouple(SCK_PIN, CS_PIN, SO_PIN); thermocouple = new SmoothThermocouple(originThermocouple, SMOOTHING_FACTOR); } void loop() { const double celsius = thermocouple->readCelsius(); display.showNumberDec((int)celsius, false); delay(500); }

Then I did the OLED thing...

/*
  Code based on:
  https://github.com/YuriiSalimov/MAX6675_Thermocouple
  https://github.com/olikraus/u8glib/
  
  OneCircuit Tuesday 20 October 23:08:11 AEDT 2020
*/ #include <Thermocouple.h> #include <MAX6675_Thermocouple.h> #include <SmoothThermocouple.h> #include "U8glib.h" #define SCK_PIN 6 #define CS_PIN 7 #define SO_PIN 8 int temperature = 0; int timer = 0; #define SMOOTHING_FACTOR 5 Thermocouple* thermocouple = NULL; U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); void draw(int howlong, int howhot) { u8g.setFont(u8g_font_unifont); u8g.setFontPosTop(); u8g.drawStr(1, 1, "OneCircuit"); u8g.drawHLine(1, 1 + 14, 78); u8g.drawStr(1, 25, "Time(s): "); u8g.setPrintPos(75, 25); u8g.print(howlong); u8g.drawStr(1, 40, "Temp(C): "); u8g.setPrintPos(75, 40); u8g.print(howhot); } void setup() { Thermocouple* originThermocouple = new MAX6675_Thermocouple(SCK_PIN, CS_PIN, SO_PIN); thermocouple = new SmoothThermocouple(originThermocouple, SMOOTHING_FACTOR); u8g.setRot180(); if ( u8g.getMode() == U8G_MODE_R3G3B2 ) u8g.setColorIndex(255); else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) u8g.setColorIndex(3); else if ( u8g.getMode() == U8G_MODE_BW ) u8g.setColorIndex(1); } void loop() { const double celsius = thermocouple->readCelsius(); temperature = int(celsius); u8g.firstPage(); do { draw(timer, temperature); } while ( u8g.nextPage() ); delay(1000); timer++; }

/*
Sketch uses 14696 bytes (44%) of program storage space.
Maximum is 32768 bytes.
Global variables use 330 bytes (16%) of dynamic memory,
leaving 1718 bytes for local variables. Maximum is 2048 bytes.
*/



Soon I'll fire up the oven with an actual PCB in it - and then mock up the ATMega328p based control/measuring unit. Will the madness ever end? <nope>







Saturday, October 17, 2020

0000 0000 0100 0101

BME280 as an altimeter

The BME280 is a useful critter which can accurately measure temperature, humidity and air pressure. It's a little more expensive than some of it's cousins (e.g. the BMP280), but packs a lot of punch into a tiny I2C driven module.


I have used the module before for tracking all three measurements (in the long running "hot house" project), but I was asked if I could make an altimeter for a school science project. Challenge accepted! Using the well known science principle that air pressure drops with altitude, I was able to adapt the code that Adafruit provides and put together a cute little project box with the required outcome.

/***************************************************************************
  Altimeter based on http://www.adafruit.com/products/2650

  OneCircuit Monday 12 October  19:27:44 AEDT 2020
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <TM1637Display.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <SimpleRotary.h>

#define CLK 2
#define DIO 3
float SEALEVELPRESSURE_HPA = 1000;
float SEALEVELPRESSURE_HPA_PREC = 0;
volatile byte pushed = 0;
volatile byte whichway = 0;
unsigned long delayTime = 500;

SimpleRotary rotary(6, 5, 7);
TM1637Display display(CLK, DIO);
Adafruit_BME280 bme;

void printValues() {
  float alt = bme.readAltitude(SEALEVELPRESSURE_HPA);
  display.setBrightness(0x0f);
  display.showNumberDec(alt);
}

void setup() {
  rotary.setTrigger(HIGH);
  rotary.setDebounceDelay(5);
  rotary.setErrorDelay(250);
  unsigned status;
  status = bme.begin();
  if (!status) {
    while (1);
  }
}

void loop() {
  pushed = rotary.push();
  if (pushed == 1) {
    pushed = 0;
    while (pushed == 0) {
      display.setBrightness(0x0f);
      display.showNumberDec(SEALEVELPRESSURE_HPA);
      pushed = rotary.push();
      whichway = rotary.rotate();
      if (whichway == 1) {
        SEALEVELPRESSURE_HPA++;
      }
      if (whichway == 2) {
        SEALEVELPRESSURE_HPA--;
      }
    }
    pushed = 0;
    while (pushed == 0) {
      display.setBrightness(0x0f);
      display.showNumberDec(SEALEVELPRESSURE_HPA_PREC);
      pushed = rotary.push();
      whichway = rotary.rotate();
      if ((whichway == 1) && (SEALEVELPRESSURE_HPA_PREC < 9)) {
        SEALEVELPRESSURE_HPA_PREC++;
      }
      if ((whichway == 2) && (SEALEVELPRESSURE_HPA_PREC > 0)) {
        SEALEVELPRESSURE_HPA_PREC--;
      }
    }
    SEALEVELPRESSURE_HPA = SEALEVELPRESSURE_HPA + SEALEVELPRESSURE_HPA_PREC / 10;

  }
  printValues();
  delay(delayTime);
}

/***************************************************************************
Sketch uses 12144 bytes (39%) of program storage space.
Maximum is 30720 bytes.
Global variables use 534 bytes (26%) of dynamic memory,
leaving 1514 bytes for local variables. Maximum is 2048 bytes.
 ***************************************************************************/

Packaged up in a box with a Nano doing the grunt work the project looks like a bit of dog's breakfast, but it actually works well as intended. If I had the time I'd look into modifying the code a bit to take into account the rotary encoder switch bounce, probably using this site as a resource.


And here is the little chap sitting on the console of our car as we bounce down our ridiculously bumpy driveway.


All in all a nice little project that shows the value of third party libraries when you need fast results to fulfill a request (in this case for an altimeter).






Saturday, October 10, 2020

0000 0000 0100 0100

ATMega8A and ATMega329P Programming Shield (PADAUK again?)

My world is coloured by PADAUK at the moment because I am like a dog with a bone.

Yeah, maybe this is bigger than anticipated

One idea for making a working FreePDK programmer is to use a reflow oven to help the soldering process. The first stage for me was to have an accurate temperature reading from the inside of the oven, close to the PCB, so that I can see the temperature profile of the oven as it heats and cools.

I can use all sorts of microcontroller options for this, but I did decide to try the ATMega8A in a 28-pin DIP package. This chip was the original μC in the Arduino UNO, before it was replaced by the ATMega328P.

Initially I wanted to press into service an AVR programming shield that arrived recently that sits atop an Arduino Uno to  program the raw μC.



In my usual staged approach™ I wrote some simple code to count on a TM1637 (which in the final project may display the temperature inside the oven). I may swap this out for an OLED that reports both time and temperature, and of course also eventually some PID code to control the oven to carefully follow a solder paste profile.

// ATMega8A and ATMega328P just count to test programmer
// OneCircuit Monday 28 September  14:35:20 AEST 2020

#include <TM1637Display.h>

// pins to talk to the TM1637 display
#define CLK 13
#define DIO 12

int currentcount = 0;             // counter
int address = 0;                // eeprom address

TM1637Display display(CLK, DIO);

void setup() {
  display.setBrightness(0x02);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
}

void loop() {

  if (currentcount > 9999) {
    currentcount = 0;
  }

  display.showNumberDec(currentcount, false);
  delay(250);
  currentcount++;
}

No change of code is needed to go between these two processors, and the compiling reports are as follows:

ATMega8A

Sketch uses 1888 bytes (23%) of program storage space. Maximum is 8192 bytes.
Global variables use 32 bytes (3%) of dynamic memory, leaving 992 bytes for local variables. Maximum is 1024 bytes.

ATMega328P

Sketch uses 2182 bytes (6%) of program storage space. Maximum is 32768 bytes.
Global variables use 32 bytes (1%) of dynamic memory, leaving 2016 bytes for local variables. Maximum is 2048 bytes.

The program works fine on both microcontrollers, and the next step is to add the thermocouple and associated MAX6675 module and then see if we can actually read/report the sort of high temperatures expected inside the oven.




Saturday, October 3, 2020

0000 0000 0100 0011

Monster Mailbag #3

I wouldn't normally do a mailbag but OMG so many (late) packages arrived so I felt the need to document the unveiling of them.

In amongst this lot are:

  1. PFS154-S08 μC
  2. UT123 Multimeter
  3. SPX3819 500mA 3.3V SOT-23 Voltage Regulators
  4. MC34063 Buck/Boost DC-DC converter IC
  5. MT3608 SOT23-6 Voltage Regulators
  6. SSP7603P33PR 3.3V 500mA SOT89-3 Voltage Regulators
  7. STM32F072C8T6 32-Bit FLASH ARM® Cortex®-M0 48MHz μC
  8. Soldering Iron Handle For Erutop 8586 Soldering Station
  9. USB Male Connectors
  10. Ridiculous Bottle Openers
  11. A4988 StepStick Stepper Driver + Heat sink
  12. SSR 10DA/25DA/ 40DA DC/AC Solid State Relay Control
  13. Awesome PCBWay stuff
Enjoy!