Photon Test Breakout Board

@rocksetta, making a jig with a known-good Photon and a target Photon makes sense. For UART testing, a simple loopback (TX connected to RX) is all that’s needed on the tested Photon. Otherwise, a simple echo test between the testing and the tested Photon is good as well.

The Photon now supports both SPI and I2C slave modes so the master would be the testing Photon and the slave the tested Photon. Modes can be reversed as long as hookup is done correctly. GPIO is straight forward as is ADC. The testing Photon could put out a voltage on its DAC that is used as inputs to the tested Photon ADCs. PWM output could tested with pulseIn() on the testing photon.

The testing board may need analog/digital multiplexers (CD4067) to configure different pin arrangements. It would be interesting to hear from the Particle folks on their test jig experience. @rickkas7 or @KyleG, can you help with that?

2 Likes

So I have started to design my Photon Testing PCB board. Actually presently working on the code to flash to the Photon in question. I really want to be able to test a photon that has cloud connectivity but perhaps a dead pin.

Question: What is the most likely pin to die? Anyone at Particle know what is the most common dead pin (probably caused by user error). Not sure who works in customer support but they should have an idea of this issue.

Would you expect Digital pins, Analog (non 5V tolerant pins…), PWM or Serial. What would people expect to burn out most without totally destroying the Photon? Possibly this is one of those things that no one person has enough information to answer.

I guess I will just have to test all pins for every ability

I am testing all the GPIO pins, by setting the next higher pin to an output and then reading for both HIGH and LOW on the present pin.

Bit strange connecting every single GPIO pin together, but it seems to work. Even spotted the error in my logic with D7. The original code connected it to D8!

Using the new Particle code sharing capabilities here is my corrected for D7 code (which will last about 5 minutes before I change it.)

… actually took about 10 minutes to fully change it. Here is the new revision.

https://go.particle.io/shared_apps/5931e36e07e2002c36000e40

2 Likes

So this seems fine for DAC testing. Was a bit more code than I was expecting.

void myTestDAC(){

// String myDAC1Good = "Bad";  //decalred as a global variable
// String myDAC2Good = "Bad";  // declared as a global variable    

int myDacRead1000, myDacRead2000, myDacRead3000;
String myDac1Output,myDac2Output ;


pinMode(DAC1, OUTPUT);    // DAC1 = A6 for output
analogWrite(DAC1, 1000);    
myDacRead1000 = analogRead(A1);
analogWrite(DAC1, 2000);    
myDacRead2000 = analogRead(A1);
analogWrite(DAC1, 3000);    
myDacRead3000 = analogRead(A1);

myDac1Output = String(myDacRead1000) + ", "+String(myDacRead2000) + ", "+ String(myDacRead3000) ;
if (myDacRead1000 > 900 && myDacRead1000 < 1100 && myDacRead2000 > 1900 && myDacRead2000 < 2100 && myDacRead3000 > 2900 && myDacRead3000 < 3100){
    myDAC1Good = "Good";
}

Particle.publish("AnalogWrite DAC1 AnalogRead A1", myDac1Output , 60, PRIVATE);
delay(1000);
Particle.publish("AnalogWrite DAC1 AnalogRead A1", myDAC1Good , 60, PRIVATE);
delay(1000);     

pinMode(DAC2, OUTPUT);    // DAC2 = A3 for output
analogWrite(DAC2, 1000);    
myDacRead1000 = analogRead(A2);
analogWrite(DAC2, 2000);    
myDacRead2000 = analogRead(A2);
analogWrite(DAC2, 3000);    
myDacRead3000 = analogRead(A2);

myDac2Output = String(myDacRead1000) + ", "+String(myDacRead2000) + ", "+ String(myDacRead3000) ;
if (myDacRead1000 > 900 && myDacRead1000 < 1100 && myDacRead2000 > 1900 && myDacRead2000 < 2100 && myDacRead3000 > 2900 && myDacRead3000 < 3100){
    myDAC2Good = "Good";
}

Particle.publish("AnalogWrite DAC2 AnalogRead A2", myDac2Output , 60, PRIVATE);
delay(1000);
Particle.publish("AnalogWrite DAC2 AnalogRead A2", myDAC2Good , 60, PRIVATE);
delay(1000);
// test both DAC lines
// schematic needs lines from DAC1 (A6) to A1;
// schematic needs lines from DAC2 (A3) to A2;
// somehow these lines need to be activated. How is this done?
// Output to console ??    

}

I really like the new revision share particle system for when I have a problem and need help, but this program is changing very quickly I think the only way to working with it is from a github site.

Sharing a revision is probably a great way to store a working backup that people can look at.

Here is the Github link

So I have PWM and AnalogRead Photon testing working on A5-A1 and A4-A0. Still makes me nervous connecting all these pins together by setting them to INPUT when not using them, but it seems to work.

The basic concept here is to use PWM to turn on an LED to 3 levels, then use- AnalogRead to read the levels from a photoresistor and a bit of fuzzy logic to check if the values are good. I needed to use my own photoresistor (inside a cylinder to block stray light) since the ones that came with the Photon were not sensitive enough.

Note:The calculation is:

myReadBig - myReadSmall > (myReadMedium - myReadSmall)*0.90

@rocksetta, you could simply connect an analog (PWM) output to a digital input and use pulseIn() to measure the pulse width for different analog output values. Or use interrupts to measure the ON/OFF times. This is more accurate and simpler than your proposed approach IMO. :wink:

My way made a lot of sense until I saw how finicky the results were. Your way makes much more sense now. Thanks :slight_smile:

Interesting: pulseIn() returns a number that is almost always 7.84 times the PWM value. Making it very easy to work with. Note: Both PWM 0 and PWM 255 return zero from PulseIn()

1 Like

How to fully reset a DAC pin?

I have a weird situation with the DAC’s:

I have expanded my DAC test to test all the analog pins. My code for both DAC1 and DAC2 works great to test all of the other analog pins (So I use DAC1 to test A3 and DAC2 to test A6). But strangely I can’t run both tests one after the other, as if once DAC1 is activated it messes up DAC2 somehow.

I know that at analogWrite(DAC1, 0); still generates about 50 mV. So I am using pinMode(pin, INPUT) to reset my pins but I am not really sure if it works on the DAC’s. I also need to have all GPIO pins interconnected (Yes I find that troubling :worried:).

The DOCS for DAC and analogRead get a bit confusing about AN_INPUT and INPUT

https://docs.particle.io/reference/firmware/photon/#analogwriteresolution-pwm-and-dac-

Does anyone have any suggestions how to fully reset a DAC pin.

Here is my full code at the moment. DAC1 works for all analog pins then DAC2 fails.

https://go.particle.io/shared_apps/5936e6a9ba82212c63000961

It almost looks like the DAC pin has an extra few volts for the first reading???

Don’t know why I have to write a question on this board before I think of a solution. :grinning:

It looks like this works to fully de-activate a DAC

pinMode(DAC1, OUTPUT);
analogWrite(DAC1, 1000); // activate DAC

digitalWrite(DAC1, LOW); // set DAC pin low NEEDED!
pinMode(DAC, INPUT); // de-activate the DAC pin

Looks like the code is good to go:

Connect all GPIO pins together, flash and run

https://go.particle.io/shared_apps/5936f388ba82215b07000a7e

Use at your own risk!

I have changed my plans slightly. I will use a differernt PCB / breadboard setup to test the serial connections. Presently have uART working just need to get I2C and SPI going.

@bko in this post:

[solved] Particle Photon not receiving i2c transmission

You have a very simple I2C Photon to Photon setup. I know the connections are:

// Photon I2C setup
// GND master to GND slave
// D0 (SDA = data) on master to D0 on slave
// D1 (SCL = clock) on Master to D1 on slave

but I am not sure about pullups when both Master and Slave are Photons both pullup to 5V or can both be pulled up to 3V3?. Any suggestions?

@rocksetta, you can pull-up to either voltages. Use 3V3 if no other I2C devices are on the bus.

2 Likes

I agree with @peekay123 here–3.3V if all devices agree, 5V otherwise.

1 Like

So working on breadboards now: Happens to coincide with my students making a few mistakes in class and frying a few Photons. The Photon-alone.ino and breadboard is currently working. I am still testing all the serial breadboards which eventually will be rolled into one (have I2C and uART working, still confused with SPI, the code not the breadboard).

Here is the github again:

Photon-alone testing Breadboard

uART Serial (GND, RX to TX and TX to RX)

I2C Serial (3V3, GND, D0, D1 both with 4.7 K ohm pullup resistors to 3V3 )

SPI Serial (GND, 3V3, A2 to A5)

@ScruffR your good at seeing my errors, other than my poor Fritzing abilities, do these serial breadboards look correct?

I am still working on the SPI, here is the docs, slave example, not sure where the master example is
https://docs.particle.io/reference/firmware/photon/#onselect-

Confused about the while(1) statement.

For your setups with a second Photon I can’t see how you power the second device? You have GND connected, but you might also want Vin or 3v3 connected.
For I2C you want 4k7 pull-ups not 470Ohm.

while(1) is usually used to trap your code in an eternal loop in case of an error condition.
But in this case it’s meant as a very tight loop to avoid any overhead introducted between loop() - but this will only work with non-AUTOMATIC SYSTEM_MODE()

Presently I just have them both powered by a usb cable, but you are correct If I use a PCB board I should use only one power source. On second thought for one of the serial connections I need the master to start before the slave which will be difficult if they are both powered together. I guess the reset button can achieve the same results.

Found this post

Looks like I will change it to 4.7 K ohm. Thanks @ScruffR

That may explain my problems with SPI. I really don’t want to switch off AUTOMATIC SYSTEM_MODE(). I have several SPI programs to test from Arduino’s and Raspberry Pi’s, sure wish someone had already got the SPI Master and Slave working on a Photon.

@avtolstoy or @mdma either of you want to add your two cents. I am trying to make some very simple: photon to photon SPI slave and master sketches. Not finding much examples so I have started my own.

I just want to send one byte from the slave to the master and one byte from the master to the slave as simply as possible. For the easiest code do you have to use onSelect and onTranserFinished as the DOCS example shows just below this link?

https://docs.particle.io/reference/firmware/photon/#onselect-

Since there is no Master example code I sort of found / changed this sketch

void setup ()
{
Particle.publish(“started”, “master”, 60, PRIVATE);
delay(2000);
SPI.begin(SPI_MODE_MASTER, SS);
digitalWrite(SS, HIGH); // ensure SS stays high for now

// Slow down the master a bit
SPI.setClockDivider(SPI_CLOCK_DIV8);

} // end of setup

void loop ()
{
char c;
// enable Slave Select
digitalWrite(SS, LOW);

// send test string
for (const char * p = “Hello, world!\n” ; c = *p; p++)
SPI.transfer ©;

// disable Slave Select
digitalWrite(SS, HIGH);

Particle.publish("Master Sent", String("Hello World"), 60, PRIVATE);
delay (5000);  // 5 seconds delay 

} // end of loop

any suggestions?

P.S. Presently SPISettings only compiles if I include Arduino.h whereas (Note the extra underscore before SPI)

__SPISettings settings(4*MHZ, MSBFIRST, SPI_MODE0);

compiles fine on its own.

Looks like something to do with

Now unsuccessfully trying:

As a master.ino

__SPISettings settings(4*MHZ, MSBFIRST, SPI_MODE0);

void setup ()
{

Particle.publish("started", "master", 60, PRIVATE);
delay(2000);
SPI.begin(SPI_MODE_MASTER, SS);

digitalWrite(SS, HIGH);  // ensure SS stays high for now

}

void loop ()
{
char c;

digitalWrite(SS, LOW);     // enable Slave Select     
SPI.beginTransaction(settings);

c = 'A';

SPI.transfer©;

SPI.endTransaction();
digitalWrite(SS, HIGH);  // disable Slave Select
Particle.publish("Master Sent", String("A"), 60, PRIVATE);
delay (5000);  // 5 seconds delay 

}

And as a slave.ino

byte val;
String myIncoming ;
bool myGotData = false;
__SPISettings settings(4*MHZ, MSBFIRST, SPI_MODE0);

void setup() {

Particle.publish("SPI slave", "Started", 60, PRIVATE);
    delay(5000);
SPI.begin(SPI_MODE_SLAVE, A2);  // slave select on PIN A2    

}

void myOnSS(uint8_t state) {
if (state){
myGotData = true;
SPI.beginTransaction(settings);
digitalWrite(A2, LOW);

    myIncoming = (char)SPI.transfer(val);
    SPI.endTransaction();
    digitalWrite(A2, HIGH);

} else { myGotData = false; }

}

void loop() {

SPI.onSelect(myOnSS);
delay(1);
if (myGotData){
    Particle.publish("SPI received bytes="+String(SPI.available()), myIncoming, 60, PRIVATE);
    delay(10000); 
    myGotData = false;
   
}

}

Still having no luck. @rickkas7 do I have to manually set all pins to the correct inputs and outputs like some SPI Arduino sketches?

This has some good info

I was unable to get a single byte SPI.transfer© to work for a SPI slave. The example in this post does 8 byte transfers, but you can simply make the data buffer smaller and it will transfer fewer bytes.

2 Likes

Thanks Rick. Very happy. Got my SPI both master and slave working really well.

I posted my code at

1 Like

Looks like my serial testing board is working. Now I just have to learn Eagle software and make a PCB for both Photon PIN testing and Photon Serial testing. How hard can that be! :slight_smile:

Here is an image of the PIN testing breadboard one of my students made:

And here is an image of the horrible looking serial test breadboard I just made.

Which actually should look like this

The console output looks like this where the Master is on top and the Slave is below

View the code at my github at

or view these shared IDE files

Photon-Alone.ino (PIN Testing) https://go.particle.io/shared_apps/5942215f7602b23810000ca1

Photon-Master.ino (uART, I2C, SPI Testing) https://go.particle.io/shared_apps/59421e547602b2ba93000b50

Photon-Slave.ino (uART, I2C, SPI Testing) https://go.particle.io/shared_apps/594221ac7602b2ba93000b7b

Now I just need some broken Photon’s that actually still have working Wifi. This is actually a bit of a problem since most of my 11 broken Photon’s don’t load Wifi :unamused: . No mater how many times I tell the students not to hook a non-micro servo up to the Photon, every few weeks some creative student gives it a try. :rage:

Can’t blame all my dead Photons on the kids, I have released my fair share of magic smoke.

1 Like