P1 - no WiFi/Cloud oscillates P1S6 pin

I have a use case where my DeviceOS v1.0.1, P1 device needs to operate in an offline mode ie without WiFi.

Am using modified @rickkas7 WiFi strategy so as to enable operation in an intranet situation, ie with WiFi but no Internet. This works a treat, but I have a very specific issue:

  • WiFi + Internet - OK
  • WiFi + NO Internet - OK
  • No WiFi - ISSUE

Here is a log showing that there is No WiFi - notice specifically the "TRACE: connect cancel" which, I think, means a Particle.disconnect has been called internally (can anyone confirm this?):

0000012692 [app] INFO: waitFor(WiFi)
0000012692 [app] INFO: WiFi.connect()
0000012739 [hal.wlan] INFO: Joining UMDHOTSPOT2
0000012739 [hal.wlan] TRACE: Free RAM connect: 20192
0000019830 [hal.wlan] ERROR: wiced_join_ap_specific(), result: 1024
0000019830 [hal.wlan] INFO: Joining UMDHOTSPOT2
0000019830 [hal.wlan] TRACE: Free RAM connect: 20192
0000026921 [hal.wlan] ERROR: wiced_join_ap_specific(), result: 1024
0000026921 [hal.wlan] INFO: Joining UMDHOTSPOT2
0000026921 [hal.wlan] TRACE: Free RAM connect: 20192
0000034014 [hal.wlan] ERROR: wiced_join_ap_specific(), result: 1024
0000036114 [hal.wlan] TRACE: connect cancel
0000036114 [hal] TRACE: 20015ae8 socket list: 0 active sockets closed
0000036114 [hal] TRACE: 20015af0 socket list: 0 active sockets closed
0000036912 [hal.wlan] INFO: Using internal antenna
0000036961 [hal.wlan] INFO: Joining UMDHOTSPOT2
0000036961 [hal.wlan] TRACE: Free RAM connect: 20224
0000042892 [app] WARN: WiFi NOT ready!

The issue shows itself within the keypad scanning class. I have a 5 x 3 matrix keypad connected to the P1's digital I/O.

One of the lines, ROW_1, is connected to P1S6. I have followed the instructions:

To enable GPIO use of P1S6, must add the following code to the setup() function or as an argument to STARTUP():
System.disableFeature(FEATURE_WIFI_POWERSAVE_CLOCK);

We have not used any external pullup resistors on the ROW_x lines, just configured the ROW pins to be INPUTS and to use their internal pullups.

The bad side effect that we are seeing via code (NOTE have not attached a logic analyser to positively confirm) is the P1S6 line is going LOW when there is no WiFi access point to connect with.

Can anyone comment on this? Is this expected?

I will now try the following software work around to this issue and report back:

  • swap columns to be inputs
  • swap rows (specifically P1S6) to be outputs

Reporting back on the swapping of I/O for the columns and rows:

  • swapped columns to be inputs
  • swapped rows (specifically P1S6) to be outputs

Same issue - but now, as expected, pressing a key connected to ROW_1, ie P1S6 pin, returns a random key on that column, ie the P1S6 line is oscillating when there is no WiFi.

Also experimented with calling System.enableFeature(FEATURE_WIFI_POWERSAVE_CLOCK) instead of System.disableFeature(FEATURE_WIFI_POWERSAVE_CLOCK) in case it was a documentation issue.

Evidence is very much pointing to System.disableFeature(FEATURE_WIFI_POWERSAVE_CLOCK) not working.

Any ideas on this?

More evidence as to what is going on:

The following shows holding down the ā€˜6ā€™ key which is on the P1S6 row:

0000091723 [app] TRACE: KP::scan(c=2,r=1)=6
0000091823 [app] TRACE: KP::scan(c=2,r=1)=6
0000091924 [app] TRACE: KP::scan(c=2,r=1)=6
0000092024 [app] TRACE: KP::scan(c=2,r=1)=6
0000092125 [app] TRACE: KP::scan(c=2,r=1)=6
0000092225 [app] TRACE: KP::scan(c=2,r=1)=6

0000092253 [hal.wlan] TRACE: connect cancel
0000092255 [hal] TRACE: 20015ae8 socket list: 1 active sockets closed
0000092255 [hal] TRACE: 20015af0 socket list: 0 active sockets closed

0000092325 [app] TRACE: KP::scan(c=2,r=1)=6
0000092427 [app] TRACE: KP::scan(c=2,r=1)=6
0000092530 [app] TRACE: KP::scan(c=2,r=0)=3
0000092531 [app] INFO: KP::getKey()=3
0000092632 [app] TRACE: KP::scan(c=2,r=0)=3
0000092733 [app] TRACE: KP::scan(c=2,r=1)=6
0000092733 [app] INFO: KP::getKey()=6
0000092834 [app] TRACE: KP::scan(c=2,r=0)=3
0000092834 [app] INFO: KP::getKey()=3
0000092934 [app] TRACE: KP::scan(c=2,r=0)=3
0000093035 [app] TRACE: KP::scan(c=2,r=2)=9
0000093035 [app] INFO: KP::getKey()=9
0000093046 [hal.wlan] INFO: Using internal antenna
0000093096 [hal.wlan] INFO: Joining UMDHOTSPOT2
0000093096 [hal.wlan] TRACE: Free RAM connect: 19864
0000093135 [app] TRACE: KP::scan(c=2,r=0)=3
0000093135 [app] INFO: KP::getKey()=3
0000093236 [app] TRACE: KP::scan(c=2,r=2)=9
0000093236 [app] INFO: KP::getKey()=9
0000093336 [app] TRACE: KP::scan(c=2,r=0)=3
0000093337 [app] INFO: KP::getKey()=3
0000093437 [app] TRACE: KP::scan(c=2,r=1)=6
0000093437 [app] INFO: KP::getKey()=6
0000093538 [app] TRACE: KP::scan(c=2,r=0)=3
0000093538 [app] INFO: KP::getKey()=3
0000093638 [app] TRACE: KP::scan(c=2,r=0)=3
0000093739 [app] TRACE: KP::scan(c=2,r=0)=3
0000093839 [app] TRACE: KP::scan(c=2,r=1)=6
0000093839 [app] INFO: KP::getKey()=6
0000093940 [app] TRACE: KP::scan(c=2,r=2)=9
0000093940 [app] INFO: KP::getKey()=9
0000094040 [app] TRACE: KP::scan(c=2,r=0)=3
0000094040 [app] INFO: KP::getKey()=3
0000094141 [app] TRACE: KP::scan(c=2,r=1)=6
0000094141 [app] INFO: KP::getKey()=6
0000094241 [app] TRACE: KP::scan(c=2,r=0)=3
0000094242 [app] INFO: KP::getKey()=3
0000094342 [app] TRACE: KP::scan(c=2,r=1)=6
0000094342 [app] INFO: KP::getKey()=6
0000094443 [app] INFO: KP::getKey()=
0000098452 [app] INFO: CheckForInternet()=0 

See how the keys randomly changed to 3, 6 or 9 after the 0000092253 [hal.wlan] TRACE: connect cancel log entry?

1 Like

Can now confirm that there is a 33 KHz clock being output on P1S6, even though the docs say:

Useful for gaining 1 additional GPIO or PWM output on the P1.
When disabled, the 32kHz oscillator will not be running on this pin

Here is is my startup code:

STARTUP(
        Keyboard.begin();           
        Serial1.begin(115200L);     // To stop, or at least reduce, spurious output upon start up
                                    // High baud rate seems to help too.
	// As we are using GPIO P1S6 for KEYPAD_ROW_1, must add:
	System.disableFeature(FEATURE_WIFI_POWERSAVE_CLOCK);
        );

@rickkas7, any comments on this? Really need this oscillation to go away....

I donā€™t have a P1 board that exposes P1S6. What Iā€™d try is build a simple app that disables FEATURE_WIFI_POWERSAVE_CLOCK that targets 0.6.3, flash that, then flash the system parts for 0.6.3 and see if the pin disconnects from the oscillator as it should.

There was an upgrade to WICED in 0.7.0 and its possible that it, or some change in Device OS, might have affected the FEATURE_WIFI_POWERSAVE_CLOCK feature. It would be nice to know when it stopped working to help narrow down the problem.

2 Likes

@rickkas7, good idea!

Will do as it is an important question to have answered.

@rickkas7,

Here is the test code:

/*  p1s6-fault.ino
    
    Testing P1S6 functionality
    Test against different DeviceOS versions
    
== Sample console output: == 

0.7.0
P1S6 Test
 Mode:AUTO
Particle connected


scan(c=0,r=0)=1     <== Key 1 Pressed
scan(c=1,r=0)=2     <== Key 2 Pressed
scan(c=2,r=0)=3     <== Key 3 Pressed
scan(c=0,r=1)=4     <== Key 4 Pressed
scan(c=1,r=1)=5     <== Key 5 Pressed
scan(c=2,r=1)=6     <== Key 6 Pressed
                    <== disabled Internet access (WiFi still up)
                    <== application blocks
                    <== enabled Internet access 
                    <== No keys pressed - P1S6 row has keys 4, 5, 6 on it
scan(c=0,r=1)=4
scan(c=0,r=1)=4
scan(c=2,r=1)=6
scan(c=1,r=1)=5
scan(c=0,r=1)=4
scan(c=0,r=1)=4
scan(c=1,r=1)=5
scan(c=1,r=1)=5
scan(c=0,r=1)=4
scan(c=0,r=1)=4
scan(c=1,r=1)=5
scan(c=1,r=1)=5
    
*/

/* Version history
2019-05-02 HR
- Created
*/


#include "application.h"

#define COMMENT   "P1S6 Test"

#define  AUTOMATIC_MODE
#undef  SEMI_AUTOMATIC_MODE
#undef MANUAL_MODE

#define NR_COLS 3
#define NR_ROWS 5

// KEYPAD I/O  - 3 x 4 matrix
// --------------------------

#define KEYPAD_ROW_0           			D4
// To enable GPIO use of P1S6, must add the following code to the setup()
// function or as an argument to STARTUP():
//		System.disableFeature(FEATURE_WIFI_POWERSAVE_CLOCK);
#define KEYPAD_ROW_1           			P1S6
// WKP
#define KEYPAD_ROW_2           			A7
#define KEYPAD_ROW_3           			D6
// DAC
#define KEYPAD_ROW_4           			A6

#define KEYPAD_COL_0           			P1S4
#define KEYPAD_COL_1           			A1
#define KEYPAD_COL_2           			P1S5

// Function Prototypes
// -------------------
char scan(void);

// Globals
// --------
uint16_t aKeypadColPins[NR_COLS] = { KEYPAD_COL_0, KEYPAD_COL_1, KEYPAD_COL_2 };
uint16_t aKeypadRowPins[NR_ROWS] = { KEYPAD_ROW_0, KEYPAD_ROW_1, KEYPAD_ROW_2,
                                    KEYPAD_ROW_3, KEYPAD_ROW_4 };


// Used to transalate from Row:Col
char aKeyMap[] = {
                   '1',     '2',    '3',      		// Row 0
                   '4',     '5',    '6',      		// Row 1
                   '7',     '8',    '9',      		// Row 2
                   (char) 0x1B,    '0',    '\r',  	// Row 3
									 'A',			'-',		'C'						
                 };



#ifdef AUTOMATIC_MODE
SYSTEM_MODE(AUTOMATIC);
#define MODE "AUTO"
#elif SEMI_AUTOMATIC_MODE
SYSTEM_MODE(SEMI_AUTOMATIC);
#define MODE "SEMI-AUTO"
#else
SYSTEM_MODE(MANUAL);
#define MODE "MAN"
#endif



// Enable use of P1S6 as GPIO
STARTUP(System.disableFeature(FEATURE_WIFI_POWERSAVE_CLOCK));


int nCountDown = 0;

void setup() 
{
    const char * pszT = "";
    
    Serial.begin(9600);
    
    // Set up I/O fopr keypad scanning
    // -------------------------------
    
	// All ROWS pulled up INPUTS
	for (int r=0; r < NR_ROWS; r++)
	{
		pinMode(aKeypadRowPins[r], INPUT_PULLUP);
	}

	// All COLS are outputs, initialse to HIGH (ie inactive)
	for (int c=0; c < NR_COLS; c++)
	{
		pinSetFast(aKeypadColPins[c]);
	    pinMode(aKeypadColPins[c], OUTPUT);
	}

#if defined(MANUAL_MODE) || defined(SEMI_AUTOMATIC_MODE)
    // Need to kick off a connection in these two modes
    Particle.connect();
#endif
    
    if (!waitFor(Particle.connected, 30000L))
        pszT = "Timed out";
    
    Serial.println(System.version());
    Serial.printf(COMMENT "\r\n Mode:" MODE "\r\nParticle connected %s\r\n\n\n", pszT );
}

void loop() 
{
    
#ifdef MANUAL_MODE
    // Connecting to WiFi manually
    // ---------------------------

    if (Particle.connected())
        Particle.process();
    else
    {
        // We are not connected, try to do so now
        // This blocks for 2000 mS
        // PROBLEM IS THAT IT DOES NOT ACTUALLY CONNECT!
        Particle.connect();

    }
#endif  // MANUAL_MODE


    // Scen the keypad every 200 ms (noting should really be 50 ms)    
    if ((millis() % 200) == 0)
        scan();
    
}   // setup()



//****************************************************************************
// scan() the keypad for key presses
//
// Returns
//			0 if no key pressed
//			!0 *decoded* ASCII key
//****************************************************************************
char scan(void)
{
    char cResult = '\0';


    for (int col=0; col< NR_COLS && !cResult; col++)
    {
        // All columns inactive (ie HIGH) except the col of interest
		for (int c=0; c < NR_COLS; c++)
		{
			// Drive the column to test (ACTIVE_LOW)
			digitalWriteFast(aKeypadColPins[c], (col == c)? LOW : HIGH);
		}

		// Let the line Settle
		delayMicroseconds(10);			// TODO This is a guess!

		// Read each row for the selected col (which is LOW)
		// LOW means key pressed (because each row is pulled HIGH)
		for (int r=0; r < NR_ROWS; r++)
		{
			// if (digitalRead(aKeypadRowPins[r]) == LOW)
			if (pinReadFast(aKeypadRowPins[r]) == LOW)
			{
			    // we have a row: map to key
		 		cResult = aKeyMap[r * NR_COLS + col];

				Serial.printf("scan(c=%d,r=%d)=%c\r\n", col, r, cResult);
				break;	// out of row scan loop
			}
		}

    }

    // turn off all columns
	for (int c=0; c < NR_COLS; c++)
	{
		pinResetFast(aKeypadColPins[c]);	// ie set LOW
	}

    return cResult;
}	// scan()

It was tested on the same hardware against DeviceOS

  • 1.1.0-rc.1 (FAIL)
  • 0.7.0 (FAIL)

I could not downgrade to 0.6.3 using OTA (have not got dfu-util on my Macbook) even though I had downgraded the bootloader to 0.5.4.

Does this assist?

@rickkas7, I had a quick look at the DeviceOS source code and can see that the enablement/disablement of the FEATURE_WIFI_POWERSAVE_CLOCK feature is a simple few lines of code (as expected).

To me it looks like there is a probability of some other process overwriting the flag as a bad side effect of WiFi / Internet dropping because once either of them have dropped, and WiFi and Internet connectivity are restored, the problem remains.

Have just raised this issue on Github: https://github.com/particle-iot/device-os/issues/1763

I note this related Github issue for the record: ā€œCan TESTMODE pin 33 (PA8) on P1 be used as an extra P1S6 pin?ā€, https://github.com/particle-iot/device-os/issues/1059.

My problem is that we have developed a PCB and are about to ā€œpress the buttonā€ in going to production with it. Unfortunately we did not pick up this issue during our validation of this boardā€¦

There is no doubt that the issue is a DeviceOS bug that should be able to be rectified.

Question is - in your opinion, how long might it be before one of your DeviceOS developers pick this up (if at all) and rectify? I know that this is a difficult question to answer, just want to know if it is typically weeks or months or very unlikely!

Thanks to @avtolstoy for sorting issue raised https://github.com/particle-iot/device-os/issues/1763 with https://github.com/particle-iot/device-os/pull/2058.

Will test once it is released and report back for completeness.