Show Posts
Pages: [1] 2 3 ... 10
1  Using Arduino / Project Guidance / Re: Ground plane EMI project solution on: January 04, 2014, 06:13:22 am
Success! After a bit of reading on twisted pairs and more on ground planes (see pics attached), I am driving the Gate from the pwm pin without capacitors, snubbers, low pass filters, with no discernable switching noise evident in 30 second dark images (with the lens cap on). The dark frames appear identical to those taken without cooling activated. I am very, very happy with the result. Temp control is rock solid.

As can be seen from the images, there are two boards. A smaller one for the mosfet with 3 planes. Gate, Drain and Source, with a high power, (high speed diode between source and drain), and the large one with power, analog and digital ground planes. The analog and digital planes are linked by a 100R resistor. The analog plane connects to one side of the Teensy and the digital, the second ground point.

I suspect that there is an optimal area for each plane, but for now it's verified as the best solution to date. For imaging purposes, I don't need to pursue this further.
2  Using Arduino / Project Guidance / Re: Ground plane EMI project solution on: January 02, 2014, 10:01:06 pm
Twisted pairs is not something I had considered and will look at rewiring the power side.

The inductor is 30pH and was designed using an on-line calculator. It's 32mm long, 1 turn and 1mm diameter - 5v silvered wire. Not sure how accurate. Came in at 0.030nH.



3  Using Arduino / Project Guidance / Ground plane EMI project solution - SOLVED on: January 02, 2014, 05:43:49 pm
This project has been ongoing, partly due to the learning curve and getting back to it after a long hiatus, working on solving the analog/digital EMI issues. Camera electronics seem to be very sensitive to digital switching. I would like guidance on some aspects of ground plane usage and connections to reduce EMI - see attached general layout/concept.

First, a general description - this setup does 3 things.

1. Cools a DSLR camera sensor to a sepoint point temperature (PWM switching through MOSFET)
2. Heats the sensor glass face for defogging - always on (Linear)
3. Heats the camera lens for dew protection -may be turned off (Linear)

A 12V SMPS (low ripple) supplies power to a TEC module and to a DC-DC convertor, which supplies 5V to the microprocessor and heaters.

Temperature control is a function of ambient air temperature vs system cooling capability - at start-up, setpoint is calculated to remain within the limits of the system given variations in ambient air temperature. A PWM value is estimated for the calculated setpoint/differential and is updated continually. Effectively, PWM dithers either side of setpoint. Maximum differential ~ 26C. Setpoint is maintained by reference to a temperature sensor attached to a copper plate conductor, which is fixed to the sensor back.

EMI

Several must do's...
The camera chassis, which is its ground, must be connected to the system ground.
MOSFET Source must be connected to Arduino/Teensy GND
High speed diode Source to Drain handles large current spikes - or so it appears

This leaves the low side switching EMI, which is proving difficult to resolve. I have tried lots of different snubbers and switching timing strategies to no effect. The most consistent method is a 22uf cap, Gate to Source. But it's not perfect. BTW it doesn't make a noticable difference whether the Gate is driven by a Gate driver or directly by PWM.

Is the EMI associated with my setup a ground loop problem (discussed on this forum many moons ago)? I thought it was solved, but with so many dead ends, I'm not convinced.

There is room in the electronics box to add PCB ground planes. It's tight, but doable. There would be 3 planes - 2 x GND, digital and analog connected by a high impedance wire, and, a +ve plate for incoming 12V from the power supply and distribution to the TEC and DC - DC convertor. However, I am a little unsure of how to set up the GND plates: that is, incoming and outgoing connections, so as to avoid bypassing any benefit provided by separating the GND sources. Eventually, all roads lead to GND.

Is it simply a matter of connecting each ground plane to separate GND points on the Arduino/Teensy? What about the power supply and DC - DC convertor GND connections. Finally, the camera chassis has to be connected to GND as well.

I've added a few pics of the project for context as well as some wave forms with and without the 400mohm resistor, which is intended to smooth/delay Gate switching - not sure how effective with and without the resistor. Electronics compartment attached to camera bottom.

OSC timebase 10us, high side resolution 10mv (red), low side, 1V resolution (blue).

The 30pH inductor -  low side, removes spikes/stray inductance in the negative node of the cap - if that makes sense. Still learning about these concepts...

Fixed the layout diagram which showed low impedance between ground planes - should be high impedance...
4  Using Arduino / Programming Questions / Re: Timing non-regular events with millis() - on: March 31, 2013, 07:57:01 am
I wish : smiley
5  Using Arduino / Programming Questions / Re: Timing non-regular events with millis() - on: March 31, 2013, 05:14:17 am
Thanks Nick - from sunny Geelong. The flasher library might be what I'm looking for, I cant see how to achieve asynchronous switching using blink without delay or millis for that matter, hence marking the time with millis and adding the desired intervals end on end. That works fine unless you want to vary the timing of the shutter 4 or 5 times in the same loop and switch out of one operation to another - add another switch? Might be easier.
6  Using Arduino / Programming Questions / Re: Timing non-regular events with millis() - on: March 30, 2013, 04:51:03 pm
Yes Paul, I realise its not the best. The post exceeded the character limit and comments were abbreviated.

As you can see the 3 main functions, integration, calibration and pause are called from loop - a 3 way sliding switch.

integrate(){ sequences the camera shutter. First, a wait time for switch debounce, next lock up the camera mirror, then wait again to let mirror settle, before firing the shutter open. When the exposure is complete the camera is repositioned by 10 - 15 sensor pixels. As the imaging session progresses, the camera describes a widening spiral. Repositioning the camera mount is performed by a stepper motor, operating in a specific pattern of steps and direction. The resulting image stack is offset frame by frame in such a way as to increase the SNR and very effectively diminish or remove sensor and optical artifacts. Frankly, I could not find a way to do this, except the table. I am working out how to do this better, but for now I want to remove delay()'s from the sketch so that they don't interfere with analog reading of temperature and humidity sensors, used for heating and eventually cooling temperature control of various ancillary services, associated with my photographical setup.

If I understand your expert jargon, correctly, I should call the shutter and dither functions from within void loop() { which would be non-blocking. As I understand it, from your explanation, the various loops are blocking and should only contain the specific digitalWrite action for each sequence called from the main loop? If that's what you mean, I get it. I see the flaw.. I was expecting different behaviour.

What about the dither table? As you may see, I want the sequence and pattern of image capture and dithering to be just so!

Calibration is no different, except that dithering is not needed. Flats are taken with an EL panel over the lens. This acts as a lens cover when switched off, to take the bias and dark frames. That is, EL panel on, take flat images, turn EL panel off, take bias and dark current images - end()

The PWM lens heater is running in the background, in loop. This could be a temperature regulated cooling system for the camera sensor or both.
7  Using Arduino / Programming Questions / Re: Timing non-regular events with millis() - on: March 30, 2013, 04:34:58 am
OK. Here it is. You will notice that I am using delay() in void calibration() because I can't get millis() Timer to work. I'm a beginner so I imagine the code is a bit clunky. I've tried to set it out as neatly as possible.

Code:
#include <Stepper.h> // include stepper library
#include <DHT.h> // include dht library

/* Stable version - This code implements millis() as a Timer to sequence DSLR shutter activation avoiding the use of delay(), automating image capture, calibration frame acquisition and PWM lens dew heater and stepper driven dither mechanism. An LED is used to indicate the status of dew heater operation; that is, failure of the dht module (low level heat cycle). To be implemented - interruption to imaging sequence warning...
 */

//set integration time

unsigned long integration = 5000UL;

//framecount

long framecount = 40;

//wait time before start

unsigned long wait = 7000UL;

//repeat light frames

bool repeat_integrate = false;

//dark frames - yes no

bool darkframes = true;

//calibration

#define biascount 5 //50;
#define flatcount 3 //10;
#define darkcount 3 //10;
int biastime = 10;
int flattime = 100;
int darktime = 3000;
int biasf = 0;
int flats = 0;
int darks = 0;

//camera settings

int mirror = 3000; // mirror lock-up time
int mkii = 500; // 5D MKII mirror lock-up
int xs = 100; // 1000D mirror lock- up
int settle = 3000; // pause between mirror and shutter
int dithert = 2000; // time before dither

//dither parameters

int frames = 0;
int steps;

//pin allocations

#define pin2 2
#define pin3 3
#define shutter 8
#define pwmPin 9
#define cap 11
#define ledPin 12

int pinval2;
int pinval3;

//time

unsigned long Timer;

//dew heater

#define DHTPIN 10 // pin 10

#define DHTTYPE DHT22

int Td; // dew point

DHT dht(DHTPIN, DHTTYPE);

//motor

#define motorSteps 200

#define motorspeed 5

#define motorPin1 4
#define motorPin2 5
#define motorPin3 6
#define motorPin4 7

Stepper stepper(motorSteps, motorPin1,motorPin2,motorPin3,motorPin4);

//dither pattern
#define steps0 50
#define steps1 50
#define steps2 -50
#define steps3 50
#define steps4 50
#define steps5 -50
#define steps6 50
#define steps7 50
#define steps8 -50
#define steps9 50
#define steps10 -50
#define steps11 50
#define steps12 50
#define steps13 -50
#define steps14 50
#define steps15 -50
#define steps16 50
#define steps17 50
#define steps18 -50
#define steps19 50
#define steps20 -50
#define steps21 50
#define steps22 -50
#define steps23 50
#define steps24 50
#define steps25 -50
#define steps26 50
#define steps27 -50
#define steps28 50
#define steps29 -50
#define steps30 50
#define steps31 50
#define steps32 -50
#define steps33 50
#define steps34 -50
#define steps35 50
#define steps36 -50
#define steps37 50
#define steps38 -50
#define steps39 50

//integration starts

void integrate(){

  if(shutter == LOW) //shutter is low
    Timer = millis();  
  if(millis() - Timer >= wait) // switch debounce lock-up mirror
    digitalWrite(shutter, HIGH);

  if(millis() - Timer >= (wait + mkii))
    digitalWrite(shutter, LOW);

  if(millis() - Timer >= (wait + mkii + settle)) //settle time for mirror slap - fire shutter
    digitalWrite(shutter, HIGH);

  if(millis() - Timer >= (wait + mkii + settle + integration)) //stop integration
    digitalWrite(shutter, LOW);

  if(millis() - Timer >= (wait + mkii + settle + integration + dithert))

    dither();
}

void dither(){

  Timer = millis();

  frames++;  

  Serial.println(frames);

  if (frames == 1)
    steps = steps0;
  if (frames == 2)
    steps = steps1;
  if (frames == 3)
    steps = steps2;
  if (frames == 4)
    steps = steps3;
  if (frames == 5)
    steps = steps4;
  if (frames == 6)
    steps = steps5;
  if (frames == 7)
    steps = steps6;
  if (frames == 8)
    steps = steps7;
  if (frames == 9)
    steps = steps8;
  if (frames == 10)
    steps = steps9;
  if (frames == 11)
    steps = steps10;
  if (frames == 12)
    steps = steps11;
  if (frames == 13)
    steps = steps12;
  if (frames == 14)
    steps = steps13;
  if (frames == 15)
    steps = steps14;
  if (frames == 16)
    steps = steps15;
  if (frames == 17)
    steps = steps16;
  if (frames == 18)
    steps = steps17;
  if (frames == 19)
    steps = steps18;
  if (frames == 20)
    steps = steps19;
  if (frames == 21)
    steps = steps20;
  if (frames == 22)
    steps = steps21;
  if (frames == 23)
    steps = steps22;
  if (frames == 24)
    steps = steps23;
  if (frames == 25)
    steps = steps24;
  if (frames == 26)
    steps = steps25;
  if (frames == 27)
    steps = steps26;
  if (frames == 28)
    steps = steps27;
  if (frames == 29)
    steps = steps28;
  if (frames == 30)
    steps = steps29;
  if (frames == 31)
    steps = steps30;
  if (frames == 32)
    steps = steps31;
  if (frames == 33)
    steps = steps32;
  if (frames == 34)
    steps = steps33;
  if (frames == 35)
    steps = steps34;
  if (frames == 36)
    steps = steps35;
  if (frames == 37)
    steps = steps36;
  if(frames == 38)
    steps = steps37;
  if (frames == 39)
    steps = steps38;
  if (frames == 40)
    steps = steps39;  

  // run stepper
  stepper.setSpeed(motorspeed);
  stepper.step(steps);

  integrate();
}

//calibration frames - flat, bias and dark

void calibration() {

  if(flats < flatcount) {
    digitalWrite(cap, HIGH);
    flat();
  }
  else
  {
    if (biasf < biascount && flats == flatcount) {
      digitalWrite(cap, LOW);
      bias();
    }
    else
    {
      if (darkframes == false) {
        end();
      }
      else
      {
        if(darks < darkcount && biasf == biascount && flats == flatcount)
          dark();
        if (darks >= darkcount) {
          end();
        }
      }
    }
  }
}

void flat() {  

  delay(1000);

  // mirror lock up
  digitalWrite(shutter, HIGH);
  delay(mkii);

  // reset shutter_pin LOW
  digitalWrite(shutter, LOW);

  // wait for mirror to settle
  delay(mkii);

  // fire shutter
  digitalWrite(shutter, HIGH);
  delay(flattime);

  // close shutter
  digitalWrite(shutter, LOW);

  flats++;
}

void bias() {

  delay(1000);

  // mirror lock up
  digitalWrite(shutter, HIGH);
  delay(mkii);

  // reset shutter
  digitalWrite(shutter, LOW);

  // fire shutter
  digitalWrite(shutter, HIGH);
  delayMicroseconds(biastime);

  // close shutter
  digitalWrite(shutter, LOW);

  biasf++;
}

void dark() {

  delay(1000);

  // mirror lock up
  digitalWrite(shutter, HIGH);
  delay(mkii);

  // reset camera_pin LOW
  digitalWrite(shutter, LOW);

  // fire shutter
  digitalWrite(shutter, HIGH);

  delay(darktime);

  // close shutter
  digitalWrite(shutter, LOW);

  darks++;
}

//pause

void pause() {

  digitalWrite(shutter, LOW);
  digitalWrite(cap, LOW);
  stepper.setSpeed(0);
  stepper.step(0);
}

//stop

void end() {

  digitalWrite(shutter, LOW);
  digitalWrite(cap, LOW);
  stepper.setSpeed(0);
  stepper.step(0);

  while (1) {
  }
}

void setup(){

  // hardware switch - set as input
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);

  // pull-up resistors
  digitalWrite(pin2, HIGH);
  digitalWrite(pin3, HIGH);

  // set as output  
  pinMode(shutter, OUTPUT);
  pinMode(cap, OUTPUT);
  pinMode(ledPin, OUTPUT);

  Serial.println("DHT test");

  dht.begin();

  Serial.begin(38400);
}

void loop() {

  //pause

  pinval2 = digitalRead(pin2);
  pinval3 = digitalRead(pin3);
  while (pinval2 == HIGH && pinval3 == LOW) {
    pause();
    break;
  }

  //imaging session integration and dither - exits on pause

  pinval2 = digitalRead(pin2);
  pinval3 = digitalRead(pin3);
  if (pinval2 == HIGH && pinval3 == HIGH) {
    integrate();
  }

  //calibration

  pinval2 = digitalRead(pin2);
  pinval3 = digitalRead(pin3);
  Serial.print(pinval2);
  Serial.println(pinval3);
  if (pinval2 == LOW && pinval3 == LOW) {
    calibration();    
  }

  //end session automatically on light frame count

  if (frames >= framecount) {
    end();
  }
  else // keep going
  {
    if (repeat_integrate == true)
      integrate();
  }

  // read humidity and temp

    float h = dht.readHumidity();
  float t = dht.readTemperature();

  // are returns valid NaN

  if (isnan(t) || isnan(h)) {

    Serial.println("Failed to read from DHT");

    // set a low level PWM value

    analogWrite(pwmPin, 127);
    digitalWrite(ledPin, HIGH);
  }
  else
  {
    // calculate dew point

    Td = t - ((100 - h)/5);

    Serial.print("Dewpoint: ");
    Serial.println(Td);

    // maintain dew point plus 4C

    int pwmD = (255 / 100)*h;

    if(t <= Td + 4) {

      analogWrite(pwmPin, 200);
    }
    else
    {
      if(t > Td + 4) {

        analogWrite(pwmPin, pwmD);  
      }
    }
  }
}
8  Using Arduino / Programming Questions / Timing non-regular events with millis() - on: March 30, 2013, 01:54:08 am
I'm using millis() to sequence dslr camera shutter events, avoiding delay because PWM is running a heater and/or cooler simultaneously.

Timing of the shutter declares timer = millis() at the beginning of the loop and adds the previous action time to the next and so on. Psuedo code below.

Code:

void integrate(){

// capture images here

  if(shutter == LOW) // must be declared or Timer routine will not work
    Timer = millis();  
  if(millis() - Timer >= 3000)
    digitalWrite(shutter, HIGH); // lock up the dslr mirror
  
  if(millis() - Timer >= 3500) // wait a while for vibrations to settle
    digitalWrite(shutter, LOW);

  if(millis() - Timer >= 6500)
    digitalWrite(shutter, HIGH); // fire the shutter again to start image capture
  
  if(millis() - Timer >= (6500 + integration)) // that done, now dither - point camera a little off from last image
    digitalWrite(shutter, LOW);

dither();
}

void dither(){

Timer = millis(); // must declare here or wont work

dither routine here then return to shutter sequence for next exposure

integrate();
}

This works fine except for missing the occasional mirror lock up, which is not ideal but tolerable. Unless Timer = millis(); is declared in void dither() no further action takes place.

When I attempt the same routine in a different loop (where it takes calibration frames) the same routine will not work and ignores the shutter timing, basically bringing everything to a halt. Same code as above, different loop location, does not work.

This is odd because Timer is just taking on the value of millis - when it is called, shouldn't matter.

What am I missing here?
9  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 17, 2013, 04:04:48 am
Tried a second emulator. No Schottky diode? Not to worry, will be sure to use one, if necessary with this snubber network?

Different results between the two simulators, so settled on the one below. A bit more setting up and the two produce similar outputs in this configuration. Decided to use the rcd snubbers after all. The mosfet output, using the simulator below was erratic - the snubbers cleaned it up and similar results from both sims.

12v supply on the TEC side is flat now, whereas it was spikey - the 10000uf cap across the supply?

dc42... many thanks.
10  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 16, 2013, 10:39:11 am
Thanks dc42. I admire your patience. I've been barking up the wrong tree, overly concerned about the mosfet spikes. All points taken, answering a number of questions and reaffirming what you have emphasised earlier. Unfortunately, Every Circuit comes with a limited set of components, which makes it necessary to improvise at times - not very helpful.
11  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 15, 2013, 11:59:04 pm
An additional capacitor was needed to remove inductance spikes with L1 at 100uH. The power supply is a 0 - 24v 15A 9mv ripple smps - do I still need the decoupling cap. L2 removed...
12  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 15, 2013, 05:07:40 am
This? I noticed that the wave form at the diode capacitor junction is identical to that of the RCD snubber in the previous post.

 I'm not sure of the capacitor and inductor values - based on stable wave form.
13  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 15, 2013, 04:07:09 am
This is the mosfet switching circuit I came up with. 2 rdc rate-of-rise voltage clamping snubbers - one for the mosfet, the other around the TEC represented by a resistor. The RC values are estimated, based on fully charging the capacitor
14  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 13, 2013, 01:55:45 pm
Thanks GM and dc42. Now that PWM and the whole mosfet switching thing is clearer to me now, I see the opportunity for a little R and D. The series inductor works at 1nh smoothing out the bottom of the wave form.

One last question. Other than contolling the mosfet switching inductance and capacitance interference, will modifying the PWM waveform by, "raising the floor", so that voltage is close to, but never zero, improve the noise issue; that is, no on/off, rather, a slightly out of square RC modified waveform?
15  Using Arduino / General Electronics / Re: 3 stage low pass filter design and performance on: March 13, 2013, 04:21:07 am
I need to minimize RF and effectively control set point - derivative control I think it is called. Having controlled one basic TEC set up with PWM, it's not suitable around sensitive electronics and the switching inductance and capacitance issues associated with the mosfet switching was a pain to filter out properly. Something I never achieved.

Tellurex also provide this discussion on TEC control, PWM and Linear. Tellurex also state that frequencies above 60hz is preferable, elsewhere they state 120hz.
Pages: [1] 2 3 ... 10