supply current: has arduino fryed my qprox sensor?

it's the $8.49 question, boys and gals.

so, my eventual aim is to make a digital theremin using the Qprox QT300 capacitance-to-digital sensor IC hooked up to arduino.

my QT300 sensors finally arrived, so i introduced one of them to arduino, uploaded some code which i calculated will let the two of them communicate according to the QT300 spec sheet, then i let them do their thing.

first run was perplexing. the 2-byte data acquisition from QT300 seemed to go ok, but all the 16bit values returned by arduino to the computer were constant, changing only every few seconds or so.

unplug. replug.

second run - the program didn't even make it past the bit where arduino requests data from the qt300 sensor. it sent the request, then just sat there waiting for QT300 to say it was ready... which it never did.

my latest hypothesis is that arduino puts out too much current through the digital pins for the QT300 to deal with. the QT300 spec sheet says that the max current is 1500 micro amps (uA), minimum 60. is it possible that this has been exceeded?? does anyone know where to get technical info about arduino's electrical specs? and if it has fryed the QT300 in this way, could anyone suggest, to a relative beginner, how to limit the current going through the sensor to a non-dangerous level (ie, below 1500uA)?

well, i should include as much info as i can. so, first up, here's the QT300 data sheet:
http://www.qprox.com/downloads/datasheets/qt300_102.pdf

secondly, this is my understanding of how arduino gets data from the QT300: (in SPI SLAVE MODE, which is the default mode of operation, unless i'm very mistaken...?) (see page 9 of the spec sheet)

basically, arduino requests data by grounding a "data request" pin ("REQ") for at least 30 microseconds. then, after a short delay, the QT300 grounds a "data ready" pin ("DRDY") to let arduino know that it has calculated the capacitance value of the theremin antenna, and is ready to send a 16-bit reading. the reading is sent in a series of 16 individual bits into the "SDI" pin on arduino, while arduino cloks out each seperate bit by setting a clock pin ("SCK") alternately high, then low, in 15-microsecond half-cycles.

make sense?

even if i alter the program to stop waiting interminably for the QT300 to say that it's ready to transmit data - that is, if i get it to sart clocking the QT300 regardless - the returned data is still always zero x 16.

next up, here's the code i wrote: (yep, feel free to use it if you're interested. let me know how you go...)

/* QT300 interface
 * ------------------ 
 * Jon Drews, 25 Jan, 2007.
 * mistersquiggle at hot mail
 * ------------------
 */

int DRDY = 2; // data ready pin
int SDI = 3;  // data input pin
int SCK = 4;  // clock output pin
int REQ = 5;  // request data output pin
unsigned int qtbytes = 0;  // stores the 16bits of data returned from QT300
int i = 0;
int x = 0;

void setup() {
  pinMode(DRDY, INPUT);
  pinMode(SDI, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(REQ, OUTPUT);
  digitalWrite(REQ, HIGH);
  digitalWrite(SCK, LOW);
  Serial.begin(9600);
  delay(1);                // dunno if this is necessary...
  Serial.println("ready...");
}

void loop(){
  digitalWrite(REQ, LOW);
  delayMicroseconds(35);      // minimum REQ pulse is 30us
  Serial.println("REQ sent");
  digitalWrite(REQ, HIGH);
  Serial.println("REQ floated high");
  Serial.print("init SDI input val: ");
  Serial.println(digitalRead(SDI));
  Serial.println("waiting for data ready signal");
  while(digitalRead(DRDY) == HIGH){
    //wait for data ready signal (DRDY low) from QT300
  }
  for (i = 0; i < 16; i++) {
    delayMicroseconds(15);    //minimum delay 12us
    digitalWrite(SCK, HIGH);  //trigger the clock pin high
    delayMicroseconds(15);    //minimum delay 13us
    x = digitalRead(SDI);
    Serial.print(x, BIN);
    Serial.print("-");
    if (digitalRead(SDI))
      qtbytes |= (1 << i);      //set individual bit in qtbytes variable using shift left
    digitalWrite(SCK, LOW);  //return clock pin low
  }
  delay(500);
  qtbytes = 0;
}

AND!

a photo of the schematic:

and the whole lot all wired up. yes, i assure you none of my uninsulated wires are touching. really...

sigh

well, any insightful suggestions very very welcome...

jon.

it's the $8.49 question, boys and gals.
my latest hypothesis is that arduino puts out too much current through the digital pins for the QT300 to deal with. the QT300 spec sheet says that the max current is 1500 micro amps (uA), minimum 60. is it possible that this has been exceeded?? does anyone know where to get technical info about arduino's electrical specs? and if it has fryed the QT300 in this way, could anyone suggest, to a relative beginner, how to limit the current going through the sensor to a non-dangerous level (ie, below 1500uA)?

Wow-- you have documented this really well.

the Arduino did not fry your QTPROX.

The 60 to 1500uA that you refer to above is the supply current for the QTProx. That means it will consumet hat much current. Long story cut short: that's what the chip needs, and in this case it isn't possible that the Arduino is 'force feeding' it more current than it needs. Think of the QTprox as a consistent load that only needs that much current.

Not sure what the problem with your circuit is, but bear in mind that capacitance-based sensors like that are notoriously fussy in terms of the layout. You would do well to order the evaluation kit for the chip, as it wil have a properly engineered layout. That might be the place to begin-- i.e. with eliminating some of the many variables.

PS: remember also that those serial println commands at 9600 baud take a long time (10ms? more?) to execute, and if they're in between the spi commands they will completely screw things up. Moral of the story: do all the SPI work, and then echo it back to the serial port of necessary.

thanks for the help daniel!

here's an update: i changed the program to pause for 1 second before initially requesting data from the QT300, and voila! it's working.... well, at least something is. the weird thing is that the 16bit data returned from the QT300 is pretty much constant, no matter how near or far my hand is from the antenna. but i set a line in the program to time the length of the QT300's acquisition burst (ie, the time between when arduino grounds the REQ line, and when the QT300 says it's ready by grounding the DRDY line). despite the same data value being returned, the acquisition time changes just as you would expect it to - when my hand is near to or touching the antenna, it drops right down. when i move my hand away, the burst time increases again.

strange.

so, if anyone has experience using a QT300 and might know what the problem is here, i'd love to hear your thoughts. it's a bit beyond me!

if you want to see the raw data from 3 different test runs with different Cs (sampling capacitor) values - i poseted them on the QProx website forum - follow the link: http://www.qprox.com/forum/read.php?f=1&i=4748&t=4748.
i forgot to mention in my post there that the data is taken over a period of about 5 seconds, with me moving my hand from about 10cm away from the antenna to a point where it almost touches. sampling rate is about 8 samples per second.

jon.

P.S.

here's my updated code.

/* QT300 interface
 * ------------------ 
 * Jon Drews, 30 Jan, 2007.
 * mistersquiggle at hot mail
 * ------------------
 *
 *  notes:
 *  burst length timing shows normal/expected results.  but 16bit data returned is almost static.
 *  tried several values of Cs capacitor.  this changes the data returned, but it is still static.  hmmmm.
 *
 */

int DRDY = 2;               // 'data ready' pin set to pin 2 on arduino
int SDI = 3;                // data input pin set to pin 3 on arduino
int SCK = 4;                // clock output pin set to pin 4 on arduino
int REQ = 5;                // 'request data' output pin set to pin 5 on arduino
byte qtbytea = 0;           // stores the first byte of data returned from QT300
byte qtbyteb = 0;           // stores the second byte of data returned from QT300
int i = 0;
int bl = 0;                 // used to count the time of the acquisition burst

void setup() {
  pinMode(DRDY, INPUT);
  pinMode(SDI, INPUT);
  pinMode(SCK, OUTPUT);
  pinMode(REQ, OUTPUT);
  digitalWrite(REQ, HIGH);    // set data request pin HIGH
  digitalWrite(SCK, LOW);     // set clock pin LOW
  Serial.begin(115200);       // set baud rate for arduino-->pc communication
  delay(1000);                // weird.  things only seem to work if i allow a 1sec pause here...
  Serial.println("ready...");
  while(Serial.available() == -1){
    // wait for any key to be pressed
  }
}

void loop(){
  qtbytea = 0;                // reset data variables
  qtbyteb = 0;
  bl = 0;                     // reset burst length var.
  digitalWrite(REQ, LOW);     // request data from QT300 by grounding the REQ line
  delayMicroseconds(80);      // minimum REQ pulse is 30us
  digitalWrite(REQ, HIGH);
  while(digitalRead(DRDY) == HIGH){
    bl++;                     // time the length of the acquisition burst.
  }
  for (i = 0; i < 8; i++) {   // loop for transfering the first byte of data from QT300 to arduino
    delayMicroseconds(20);    // minimum delay 12us
    digitalWrite(SCK, HIGH);  // trigger the clock pin high
    delayMicroseconds(20);    // minimum delay 13us
    if (digitalRead(SDI))
      qtbytea |= (1 << i);    //set individual bit in qtbytea variable using shift left
    digitalWrite(SCK, LOW);   //return clock pin low
  }
  i = 0;
  for (i = 0; i < 8; i++) {   // loop for transfering the second byte of data from QT300 to arduino
    delayMicroseconds(20);
    digitalWrite(SCK, HIGH);
    delayMicroseconds(20);
    if (digitalRead(SDI))
      qtbyteb |= (1 << i);
    digitalWrite(SCK, LOW);
  }
  Serial.print(qtbytea, BIN);  // print the first byte in binary format
  Serial.print("-");
  Serial.print(qtbyteb, BIN);  // print the second byte in binary format
  Serial.print(" BL: ");
  Serial.println(bl, DEC);     // print the length of the acquisition burst.  then do a line break.
  delay(100);                  // wait a bit to avoid flooding the serial port with data
}

terrific... why don't you write it up as a tutorial, so that the infomation can be used by the next person who wants to do this?
You can post it in the 'Playground' wiki.

wheeee! i don't believe it, but i've just managed to get the whole thing working perfectly. turns out, i was reading the bits returned from QT300 backwards, shifting left instead of right. silly me. but yes. i shall post this as a tutorial in a week or so when i get back from travelling.

next up is improving the stability of the system - currently, using a 100nF sampling cap, the data returned ranges from about 2200 (far) to 800 (near), but has a noise level of about +/- 15 which is totally unuseable for precision control.

some improvements i'm considering:

  • isolating the QT300 from arduino, powering it on it's own battery supply to get rid of power rippling (i'm sure arduino's USB power output isn't crash hot in terms of ripple - can anyone verify this?)

  • adding some shielding around the QT300 (could anyone suggest some good literature on how shielding works? i know absolutely nothing, except that i should keep my ground traces away from the sensor electrode...)

  • perhaps try using optocouplers or some other kind of circuit isolation (again, i know nothing. do optocouplers work fast enough to allow microsecond-accurate transfer of data, or does anyone know of some other similar gadget that does?)

  • trying to increase the sensitive distance of the antenna. starting with researching antenna design - how shape, length, material, etc. affect the sensitivity characteristics. i don't even know if the QT300 is capable of projecting the sensitivity field, or whatever you call it, through more than about 10cm of air. i'm hoping i can overcome this somehow, because 10cm is pretty useless to a theremin player...

hmmmm. so i've sill got quite a fair way to go on this one. but at least the first big hurdle is pretty much sorted out. any suggestions welcome!

jon.

Hi Jon

thanks very much for everything you've posted, you have no idea how much trouble you have saved me!

I have my qt300 sending SPI to my arduino, but now I want to use the 1-wire UART mode of the qt300, since it will greatly reduce the wiring complexity of my system ( I am using multiple qt300s). I already have code to do the 1-wire comm, but I first need to change modes of the qt300.

According to this thread on the quantum forum:

http://www.qprox.com/forum/read.php?1,1370

You can program the chips to change modes with only a microcontroller, rather than buying the programmer.

I am about to do this, but I wanted to check if anyone here has done this, and can give some pointers.

Well I've managed to do it. BTW Jon, I noticed in your code that your bytes are flipped around, ie you're reading in the MSB first and then shifting the less significant bits to the left. Is there a reason for that?

How did you manage to set the QT300 into 1-wire mode, and can you post a schematic of how it works with the arduino in 1-wire mode?

Thanks.

S

hmmm, i'm not all that sure about 1-wire mode. i'm using the chip as it comes out of the box: in 4-wire SPI slave mode. to set it to 1-wire mode i think you need a special cloning adapter (QTM300CA) to change the relevant parameter. from memory, i think it will cost more than an arduino... here's the user's guide:

http://www.qprox.com/downloads/manuals/qtm300ca_102.pdf

but you'd better chack that it's what you need before forking out the cash. also, if you just want to run several QT300s with one arduino, there's a section in the QT300 datasheet that explains how to use several chips over a single SPI interface. i think you need 3 common wires, then one wire for each chip...?

j.