Sparky: pumps

I wired up the second pump, which runs at a different voltage to the first pump, to Sparky, so we now have boards with voltages of 48v, 24v and 12v. I don’t think I’m going to be looking at 6.

I /think/ the 12v is 12v. I just got hit by a nagging suspicion that’s my stepdown to 24 and now I just don’t know. Balls. I mean, I know at the time that I tried to make a stepdown and then I found the board thta did it… but did I know at the time or did I just remember knowing? Doppleballs.

Sparky – resistor array

Sparky’s first spark-board resistor was 100ishR, 1/8W, and the magic smoke escaped instantly. The second was 50R, a couple of orders larger in wattage, and much much bigger, and made of metal. After we’d been running the spark table for a while, there was a wisp of smoke from the table, which was starting to melt. So we found four of those in an array, and we wired them up to give us 50R, and they get uncomfortably hot to touch. They’re mounted on an aluminium plate.

Today, Mat converted a lump of car radiator into a heat sink, drilling and tapping all the holes necessary to fit five waaaay chunkier 10R resistors on so we can wire them up with crocodile clips. If we need to water cool them, we can borrow some resistors from someone I know who worked in sound. If /that/ fails, he was telling me about spikes and power switching, and that’s a spare thought. However, this array ought give us a good range from 2-50R, depending on how we wire them, and if 2 Ohms doesn’t set fire to anything, we’re likely to stick with that.

Today, I helped by making tea and not getting in the way, and as a san-check on the positioning of the drill holes, and I also learned a bit about clamping. Mat helped by doing all of the work, and not fucking it up, and also by making tea.

Sparky v2 – latest code

The code for Sparky Version 2 is just about finished. I need to swap something I did back-to-front with something Mat did far more elegantly and in fewer lines, but the logic’s sound. Here, with a bit of editing, is Oxygen v7. V1-5 were debugging programs of various sorts.

/* Version 7 of Oxygen is the software implementation.
 * 
 * We do not use pins 0 & 1 (RX/TX) for the main board.
 * We scan LVL after smoothing, compare to the set voltages of 'max_trigger', and 'min_trigger' trigger DIR to 1 or 0 if we want to move.
 * We then hit STEP.
 * Pins should be set to cross directly to DIR and STEP, on veroboard.
 * For convenience, we begin crossing at pin 3, with pin 2 being the zoom toggle
 * 
 * For debugging, we output LVL, MAX, MIN, DIR to serial, and comment that out.
 * 
 * Arduino takes in LVL and four cut-out or direction override pins, plus one 'zoom' pin to speed up or slow down stepping in software, and outputs 7 pins - M0, 1, 2, Step, Dir, /Sleep, /Reset

 */

// hardware constants for board input/output

const int ledPin = 13;
const int zoomPin = 2;  // earth to 0v on Arduino board to increase speed (decrease software delay)

// digital (output) pins (Arduino Pro Mini matched to DRV8825 Stepper Driver)
const int dirPin = 3;
const int stepPin = 4;
const int sleepPin = 5;
const int resetPin = 6;

// step size pin array
int mPins[3] = {7, 8, 9};
const int mPinCount = sizeof(mPins)/sizeof(int);
int mPinStates[mPinCount] = {};
// char *mPinNames[mPinCount] = {"M0", "M1", "M2"};  // Probably only ever in debugging/humanised printing

// Input for cut-outs and manual drive
const int upperCutoutPin = 10;
const int lowerCutoutPin = 11;
const int driveUpPin = 15;  // A1 Can be used as digital pin.
const int driveDownPin = 16;// A2 can be used as digital pin.

// analogue (measurement) pins
const int levelPin = A0;

// measurement constants
/* lvl = 0...1023 (corresponding to 0 to 5v ish) */

const int AnalogReadsPerVolt = 200;  //1000 ish corresponds to 5v

#define volts  // defines volts as a word to ignore by defining it as blank

const int max_trigger = 1 volts * AnalogReadsPerVolt;
const int min_trigger = .1 volts * AnalogReadsPerVolt;

// measurement variables

int lvl = 0;

// move-related variables and calculations

int move_rate = 100;  // Used for speeding up/slowing down in software
int step_ratio = 1;   // Valid options, 1, 2, 4, 8, 16, 32
int step_index = 0;   // used to keep track of which result we want
int stepsize_results[] = {32, 16, 8, 4, 2, 1};
const int stepsize_count = sizeof(stepsize_results) / sizeof(int);
int modePinSettings[stepsize_count] = {5, 4, 3, 2, 1, 0}; // read from High/Low table in docs, M2 first

/* Finds index within modePinSettings, to give us a later result */
int find_index(int array[], int count, int value)
{
  int i;
  for(i=0; i>= 1;
  }
  
  
  digitalWrite(sleepPin, HIGH); // /SLEEP - high to suppress behaviour
  
  // Reset Stepper Board 
  digitalWrite(resetPin, LOW);
  delay(5);
  digitalWrite(resetPin, HIGH); // /RESET
  digitalWrite(ledPin, HIGH);

  //Serial.print("Initialised with min ");
  //Serial.println(min_trigger);
  
}

void loop()  {
  
  
  if(digitalRead(zoomPin) == LOW){  // move rate will appear twice in each loop that moves, once in each loop that does not move
    move_rate = 50;
  } else {
    move_rate = 500;}
  //Serial.print("zoomPin: ");
  //Serial.print(digitalRead(zoomPin));
  //Serial.print("move_rate: ");
  //Serial.println(move_rate);
  
  
  if(digitalRead(driveUpPin) == LOW) {
    //Serial.println("Drive pin: Up.");
    stepUp(move_rate);
  } else if(digitalRead(driveDownPin) == LOW) {
    //Serial.println("Drive pin: Down.");
    stepDown(move_rate); // Behaviour under thick fingers: shout at clumsy person
  } else {  

    lvl = analogRead(levelPin);
    
    if(lvl < min_trigger) {
      //Serial.println("Calling stepUp()");
      stepUp(move_rate);
      // //Serial.println("Moving Up.");  // debugging line
    }
    else if(lvl > max_trigger) {
      //Serial.println("Calling stepDown()");
      stepDown(move_rate);
      // //Serial.println("Moving Down.");  // debugging line
    } else {//Serial.println("Fallthrough.");
    } // lvl not triggering either threshold.  Try earthing it to be sure it goes up.
  }
}

Sparky v2 – analogue and digital

Veroboard with wires, an arduino, and some smoothing capacitorsI’ve soldered up most of the board for Sparky v2, meaning I now know which pins connect where. The Arduino has analogue pins that can also be used for digital input, so although I’m technically out of digital pins, that’s not really a problem. I’ll be testing that theory soon, using a digital read instead of an analogue read, and I’m pretty sure it’ll end up fine. I’ve written the code, soldered most things, but need some small push buttons to test the code entirely, and I don’t want to put on the stepper driver chip before it’s entirely tested.

Sparky v2 – electronics layout

The Version 1 main board of Sparky has a circuit diagram which is neatly broken up into bits, so that every bit does one thing, and they can all be chained together to make up a whole circuit. When we had to add things, it was easy to do, because the diagram was already in bits, so we could swap bits in and out. So, I’m going to try that here. I’ll name each bit for the part, and you should be able to walk through from any part to the end result of that particular bit. Later, I’ll break down the individual bits to their actual wiring, inputs, and outputs. Important parts like capacitors are here so I don’t forget them later, and do not indicate I think a bit is finished.

Power (24 v) -> voltage converter -> 12v and 5v

12v -> smoothing capacitor -> Stepper Driver

12v -> Water pumps (filter and probe, or all in one)

Spark Power -> Spark Board* -> Spark Probe*

Spark Board* -> LVL* -> Arduino

Board cut-outs -> Arduino (input pull-ups)

Frame cut-outs (end stops) -> Arduino

5v Power Indicator LED

Arduino -> Stepper Driver

Reset mini button -> Stepper Driver

Stepper Driver -> Stepper*

* Solved problem/finished item

The spark board sits on a flying lead, and can be put in at any time. The board cut-outs allow us to drive the stepper in the opposite direction to the expected one, by over-riding the rest of the electronics, meaning we can force the probe up or down. The frame cut-outs are safety interlocks, which stop our motor when we are about to go too far, to protect the parts.

So the Arduino will be taking in the LVL pin, and four different cut-outs, and outputting five instruction pins. (Step, Direction, M0, M1, M2). It will also output the Reset pin so we can be sure the stepper driver is following the Arduino and not moving during boot-up, and the sleep pin, so we can control its waking state. The 5V line itself will power the driver itself, so we can’t power it without the LED coming on. I think the main danger to the driver is if we’re running power through the 12v line when we accidentally unplug it, so that might get changed, but for now I’m planning not to power the driver through the Arduino, which might under exceptional circumstances be powered to 5v while the board is off.

ETA: I had a quick convo with Mat and hardly made him wince at all, and I’ve reduced the 24 volt stepper/pump power line to 12 volt, and I’m happier than I was about them being on the same supply. He’s happier than he was because I told him I wasn’t in the same city as him. I was lying, but we do that for people we like. I’m told.

Sparky, redesign in software

So, I’ve probably learned everything I can about electronics from this particular TTL build. For example, I now know what TTL stands for, what 5 volts tastes like, and what a pull-up resistor is. Mat knows that explaining things to a non-expert is haaaaard and that left alone I will do crazy things. So we’ve both learned.

The main board of Sparky is a horror of add-ons, re-mapping, remaking and coloured wires. At least the coloured wires are consistent. Orange for one side of the level we want, green for the other. However, I need to replace most of the bits of the main board with the Arduino.

The step-down needs to be done in hardware. I’m not running 40 volts through an Arduino, even to see what happens[0]. The level comparisons can be done at 5 volts, and indeed it’ll be easier to do that then to twiddle analogue knobs. The first thing we’ll be finding out is whether we’re grounded. If the probe is touching the material, we want to move up. (If we can’t move up, for example because we just hit a switch and the material fell over on the probe, we probably want to cut off the spark circuit, but I’m not building relays into this.)

We want to avoid false positives, so we check a smoothed version of LVL. That smoothing is also done in hardware, with a capacitor.

If the probe isn’t touching the material, then we test to see if the smoothed LVL (see, we’re using the function, or at least a value we passed along) is 0. If so, we move down.

If neither of those things is the case, we leave well alone for Tau, where Tau is the period of the spark capacitor charging. Then we loop again.

‘move’ here is a function, which tells the stepper chip DIR, and then hits the STEP pin. I’m guessing we can do that in two lines of code, and the pause between them will be enough, but DIR might take a moment to wake up, and if that happens it can be dealt with.

So, the shape of it:

LVL +
    |
    +--Check not grounded -- if grounded move up then start loop again.
         |
         + Check not high -- if high, move down then start loop again.
             |
             + If nothing else, stay where you are for Tau then start loop again.

Things I’ll need:

  • LVL measurement – this will expand the timing loop if we end up sampling repeatedly
  • comparator function – /U and /D variables, vs LVL. Check that /U and /D are different and in the correct order – if no space between them, abort and complain.
  • spark delay calculator/outer timing loop
  • movement function
  • tea

On the wishlist:

  • Serial.print output in various formats
  • M0 M1 M2 pins to be isolated with dipswitches. Whatever they are.
  • more tea

[0] If I were going to be doing that, I’d use considerably higher voltage.

Sparky – the state of the code 2015-07-24

Sparky is pretty much functional, and needs making into something good. I’ve re-written the Arduino code with what I’ve learned so far in Learn C the Hard Way, and I’ll use the same board as the Arduino’s on to trigger electronically isolated LEDs, meaning I don’t have to have any outputs, so I can use all the pins for measuring.

The code is as generic as I can make it. Other than the LED pin, none of the pins come pre-named, so you can decide what to plug in where and how, and then output it, as long as you have this program and an Arduino programmer.

/*
 * 
 * Version 6 of Oxygen is an almost complete re-write.
 * V6 mounts the LEDs on the in pins, allowing for easy reading, without needing output.  Physical output can be provided by buffering LEDs to numbered pins.
 * V6 has a timing loop of one second, followed by a toggle of the LED on reserved Pin 13.
 * We do not use pins 0 & 1 (RX/TX).
 * We scan as many lines as we can find pins for, and store them in an array so we can do good things with them.
 * The output to Serial Monitor has two possible outputs of human-readable including pin names, or binary string.
 * 
 * TO DO: binary output function for Serial Monitor
 * TO DO: use millisecond timing from boot-up rather than a set delay to make the timing loop 1 second
 * TO DO: Import oscillator code from V5, as separate function applicable to any pin
 * TO DO: Function to map analogue pins to arbitrary voltage levels (default 5v 2 decimal places).
 * 
 * May^wDoes contain sarcasm.
 */

// unchanging constants and annoying variables

// #include <stdarg.h> - use for more elegant printing later - Mat to show me how.  #includes are not generally needed in Arduino - implicit functions are brought in automatically

// Blink stuff
int ledState = LOW;
int ledPin = 13;


// Pin Arrays that I will later resent treating this way

// digital (measurement) pins

int digitalPinNumbers[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};  // Leave out Pin13.
const int digitalPinCount = sizeof(digitalPinNumbers)/sizeof(int);  // const so we have a non-variable for indexing
char *digitalPinNames[digitalPinCount] = {"Pin 2", "Pin 3", "Pin 4", "Pin 5", "Pin 6", "Pin 7", "Pin 8", "Pin 9", "Pin 10", "Pin 11", "Pin 12"};  // also leave out pin 13
int digitalPinStates[digitalPinCount] = {HIGH}; // Currently working with pull-up resistors.  To be changed.

// analogue (measurement) pins

int analoguePinNumbers[] = {A0, A1, A2, A3, A4, A5}; // A4 & A5 are hard to get to thus likely to float
const int analoguePinCount = sizeof(analoguePinNumbers)/sizeof(int);
char *analoguePinNames[analoguePinCount] = {"Pin A0", "Pin A1", "Pin A2", "Pin A3", "Pin A4", "Pin A5"};
int analoguePinStates[analoguePinCount] = {};


// misplaced functions I will later regret

// !!! TO DO - add binary output !!!

void HumanPrint(){

  Serial.println("Digital Pins");
  for(int i = 0; i < digitalPinCount; i++){
    digitalPinStates[i] = digitalRead(digitalPinNumbers[i]);
    Serial.print(digitalPinNames[i]);
    Serial.print(": ");
    Serial.println(digitalPinStates[i]);
  }
  Serial.println("Analogue Pins");
  for(int i = 0; i < analoguePinCount; i++){
    analoguePinStates[i] = analogRead(analoguePinNumbers[i]);
    Serial.print(analoguePinNames[i]);
    Serial.print(": ");
    Serial.println(analoguePinStates[i]);
  }

}
void setup(){
  Serial.begin(9600);
  
  for(int i = 0; i < digitalPinCount; i++){
    pinMode(digitalPinNumbers[i], INPUT_PULLUP);
  }
  for(int i = 0; i < analoguePinCount; i++){
    pinMode(analoguePinNumbers[i], INPUT);
  }
  pinMode(ledPin, OUTPUT);
  Serial.println("Initialised."); 
}

//Do this later - Mat to demo
//void SerialPrint(char *v0, varargs ...)
//{
//}

void loop() {

  HumanPrint();
  
  ledState = !ledState;
  digitalWrite(ledPin, ledState);
  delay(1000);
}