-
Notifications
You must be signed in to change notification settings - Fork 15
Open
Description
I started this issue just to point out that I recently added some test code to the old issue readBlockData() sometimes times out after 200ms. It had been a couple of months since anyone last posted to that issue, so I'm thinking it was assumed inactive. Everything I'm posting here is also posted to the original issue.
Anyhow, here's a recap of the original issue:
We have 7 analog input modules on our P1AM-100 system:
- Power supply: P1-01AC on 120VAC
- Shield: P1AM-SERIAL with nothing connected.
- CPU: P1AM-100 with USB serial to a PC
- Module 1: P1-04AD
- Module 2: P1-04RTD
- Modules 3-7: P104THM
- Module 8: P1-08TRS (Relay outputs)
The following code usually works, but occasionally times out after 200ms. It does this even if we have nothing attached to any modules.
char buffer[112];
P1.readBlockData(buffer,112,0,ANALOG_IN_BLOCK);
This is with Arduino IDE 2.3.5 and P1AM 1.0.9.
Here's the new test code. This is an exact copy/paste from the *.ino file. On my system, this fails 3-5 times per hour.
Notes:
- The switch on the P1AM-100 is in the up position.
- Nothing is attached to any of the I/O modules.
- The P1AM-100 is powered directly from 120VAC in my office cube.
- I commented out #define DEBUG_PRINT_ON in defines.h, as described in the comment on line 50.
//! @file P1AM-100_Test.ino
// Use debugging print statements. (Comment out to turn off print statements.)
#define TESTER_DEBUG
// Debugging print statements.
#ifdef TESTER_DEBUG
#define DEBUGPRINT(VALUE...) do {Serial.print(VALUE);} while(0)
#define DEBUGPRINTLN(VALUE...) do {Serial.println(VALUE);} while(0)
#else
#define DEBUGPRINT(VALUE...) do {} while(0)
#define DEBUGPRINTLN(VALUE...) do {} while(0)
#endif
#include <P1AM.h>
#include <P1AM_Serial.h>
const int JUNKCOUNT = 1000;
unsigned long junk[JUNKCOUNT];
void ConfigureIO(void)
{
// P1-04AD: https://facts-engineering.github.io/modules/P1-04AD/P1-04AD.html
// Enable ch 1-4, 0-10V, 0-20mA, 0-20mA, 0-10V.
const char P1_04AD_CONFIG_1[] = { 0x40, 0x03, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x22, 0x03, 0x00, 0x00, 0x23, 0x01 };
// P1-04RTD: https://facts-engineering.github.io/modules/P1-04RTD/P1-04RTD.html
// Enable ch 1-4, High Side Burnout, Fahrenheit, Pt1000, 33Hz/16bit/61ms.
const char P1_04RTD_CONFIG_2[] = { 0x40, 0x03, 0x60, 0x07, 0x20, 0x02, 0x80, 0x00 };
// P1-04THM: https://facts-engineering.github.io/modules/P1-04THM/P1-04THM.html
// Enable ch 1-4, High Side Burnout, Fahrenheit, Type J, J, J, J.
const char P1_04THM_CONFIG_3[] = { 0x40, 0x03, 0x60, 0x07, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Enable ch 1-4, High Side Burnout, Fahrenheit, Type J, J, K, K.
const char P1_04THM_CONFIG_4[] = { 0x40, 0x03, 0x60, 0x07, 0x21, 0x00, 0x22, 0x00, 0x23, 0x01, 0x24, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Enable ch 1-4, High Side Burnout, Fahrenheit, Type T, T, T, T.
const char P1_04THM_CONFIG_5[] = { 0x40, 0x03, 0x60, 0x07, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Enable ch 1-4, High Side Burnout, Fahrenheit, Type T, T, T, T.
const char P1_04THM_CONFIG_6[] = { 0x40, 0x03, 0x60, 0x07, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Enable ch 1-4, High Side Burnout, Fahrenheit, 0-1.25V, 0-1.25V, 0-1.25V, 0-1.25V.
const char P1_04THM_CONFIG_7[] = { 0x40, 0x03, 0x60, 0x07, 0x21, 0x0e, 0x22, 0x0e, 0x23, 0x0e, 0x24, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// P1-08TRS: https://facts-engineering.github.io/modules/P1-08TRS/P1-08TRS.html
// No configuration for P1-08TRS.
// Note: comment out #define DEBUG_PRINT_ON in defines.h so P1.init() won't print a list of modules to the serial port.
// On Windows machines, defines.h is probably at %HOME%\Documents\Arduino\libraries\P1AM\src.
while (!P1.init())
{
; // Wait for Modules to Sign on.
}
// Configure modules.
P1.configureModule(P1_04AD_CONFIG_1, 1); // Config data to the module in slot 1.
P1.configureModule(P1_04RTD_CONFIG_2, 2); // Config data to the module in slot 2.
P1.configureModule(P1_04THM_CONFIG_3, 3); // Config data to the module in slot 3.
P1.configureModule(P1_04THM_CONFIG_4, 4); // Config data to the module in slot 4.
P1.configureModule(P1_04THM_CONFIG_5, 5); // Config data to the module in slot 5.
P1.configureModule(P1_04THM_CONFIG_6, 6); // Config data to the module in slot 6.
P1.configureModule(P1_04THM_CONFIG_7, 7); // Config data to the module in slot 7.
return;
} // ConfigureIO
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else // __ARM__
extern char *__brkval;
#endif // __arm__
int freeMemory()
{
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}
//! @brief Recursive function, to use the stack.
unsigned long recursion(int levelsToGo)
{
unsigned long timeStamp = millis();
if (0 == levelsToGo)
{
return timeStamp;
}
return timeStamp + recursion(levelsToGo - 1);
}
//! @brief Setup code, to run once at startup.
void setup()
{
// Set LED to be a digital output.
pinMode(LED_BUILTIN, OUTPUT);
// Turn on the LED.
digitalWrite(LED_BUILTIN, true);
// Initialize and configure I/O modules in the base.
ConfigureIO();
// Open serial communications.
Serial.begin(115200);
// Wait for USB serial port to connect.
while (!Serial)
{
; // Wait for serial port to connect. Needed for native USB port only.
}
DEBUGPRINT("Available memory = ");
DEBUGPRINTLN(freeMemory());
return;
} // setup
//! @brief Loop code, to run repeatedly after setup is complete.
void loop()
{
bool analogFailure = false;
const int ANALOGINPUTBLOCKLEN = 4*4*7; // 4 bytes/channel, 4 channels/module, 7 modules.
char analogInputData[ANALOGINPUTBLOCKLEN]; // Data for block read of analog modules.
// Use switch to blink LED.
digitalWrite(LED_BUILTIN, (millis()%500) < 250); // Blink LED at 2Hz.
for (int i = 0; i < JUNKCOUNT; i++)
{
junk[i] = millis();
}
recursion(100); // Use the stack.
// Read data as a block.
unsigned long timeStamp_ms = millis(); // We want to see how long the calls to readBlockData() take.
P1.readBlockData(analogInputData,16,0,ANALOG_IN_BLOCK);
unsigned long duration_ms_1 = millis();
P1.readBlockData(analogInputData + 16,16,16,ANALOG_IN_BLOCK);
unsigned long duration_ms_2 = millis();
P1.readBlockData(analogInputData + 32,16,32,ANALOG_IN_BLOCK);
unsigned long duration_ms_3 = millis();
P1.readBlockData(analogInputData + 48,16,48,ANALOG_IN_BLOCK);
unsigned long duration_ms_4 = millis();
P1.readBlockData(analogInputData + 64,16,64,ANALOG_IN_BLOCK);
unsigned long duration_ms_5 = millis();
P1.readBlockData(analogInputData + 80,16,80,ANALOG_IN_BLOCK);
unsigned long duration_ms_6 = millis();
P1.readBlockData(analogInputData + 96,16,96,ANALOG_IN_BLOCK);
unsigned long duration_ms_7 = millis();
unsigned long duration_ms = duration_ms_7 - timeStamp_ms; // Duration of all readBlockData() calls.
// Each "duration" is currently just a timestamp.
// Subtract consecutive timestamps to get the actual durations.
duration_ms_7 -= duration_ms_6; // Duration of module 7 readBlockData() call.
duration_ms_6 -= duration_ms_5; // Duration of module 6 readBlockData() call.
duration_ms_5 -= duration_ms_4; // Duration of module 5 readBlockData() call.
duration_ms_4 -= duration_ms_3; // Duration of module 4 readBlockData() call.
duration_ms_3 -= duration_ms_2; // Duration of module 3 readBlockData() call.
duration_ms_2 -= duration_ms_1; // Duration of module 2 readBlockData() call.
duration_ms_1 -= timeStamp_ms; // Duration of module 1 readBlockData() call.
// See if the calls to readBlockData() took too long.
if (50 < duration_ms)
{
// Print debug message if the failure just happened, not if it's ongoing.
if (!analogFailure)
{
DEBUGPRINT("readBlockData total "); DEBUGPRINT(duration_ms); DEBUGPRINTLN(" ms");
DEBUGPRINT("readBlockData parts "); DEBUGPRINT(duration_ms_1); DEBUGPRINT(" ");
DEBUGPRINT(duration_ms_2); DEBUGPRINT(" "); DEBUGPRINT(duration_ms_3); DEBUGPRINT(" ");
DEBUGPRINT(duration_ms_4); DEBUGPRINT(" "); DEBUGPRINT(duration_ms_5); DEBUGPRINT(" ");
DEBUGPRINT(duration_ms_6); DEBUGPRINT(" "); DEBUGPRINT(duration_ms_7); DEBUGPRINTLN(" ms");
// The call to readBlockData() took too long. P1 modules must be reconfigured.
analogFailure = true;
}
}
// Recover if base loses power or analog input failure.
if((P1.isBaseActive() == false) || analogFailure)
{
DEBUGPRINTLN("Base lost power or analog failure.");
DEBUGPRINT("Timestamp: "); DEBUGPRINT(millis()); DEBUGPRINTLN(" ms");
while (!P1.init())
{
DEBUGPRINTLN("Waiting for power;");
delay(500);
}
// Power has been restored to the base.
DEBUGPRINTLN("Power returned;");
// Set the LED to match the switch state.
digitalWrite(LED_BUILTIN, digitalRead(SWITCH_BUILTIN));
// Initialize and configure I/O modules in the base.
ConfigureIO();
DEBUGPRINTLN("Analog modules configured");
analogFailure = false;
} // Base lost power or analog input failure.
// Read all serial data from USB serial port.
while (Serial.available())
{
Serial.read();
}
return;
} // loop
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels