Merge pull request #4 from 0ussama/scancycle

Separates the input and output updates in two functions. This improves OpenPLC scan cycle as it starts processing with an accurate representation of the inputs.
This commit is contained in:
Thiago Alves 2017-09-18 14:49:42 -05:00 committed by GitHub
commit d9bad37a94
10 changed files with 220 additions and 57 deletions

View File

@ -560,10 +560,10 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex bufferLock
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
//Lock mutexes
pthread_mutex_lock(&bufferLock);
@ -581,6 +581,21 @@ void updateBuffers()
if (int_input[i] != NULL) *int_input[i] = input_data.analog[i];
}
pthread_mutex_unlock(&ioLock);
pthread_mutex_unlock(&bufferLock);
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
//Lock mutexes
pthread_mutex_lock(&bufferLock);
pthread_mutex_lock(&ioLock);
//Digital Output
for (int i = 0; i < (sizeof(output_data.digital)*8); i++)
{
@ -595,4 +610,4 @@ void updateBuffers()
pthread_mutex_unlock(&ioLock);
pthread_mutex_unlock(&bufferLock);
}
}

View File

@ -42,10 +42,32 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex bufferLock
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
pthread_mutex_lock(&bufferLock); //lock mutex
/*********READING AND WRITING TO I/O**************
*bool_input[0][0] = read_digital_input(0);
write_digital_output(0, *bool_output[0][0]);
*int_input[0] = read_analog_input(0);
write_analog_output(0, *int_output[0]);
**************************************************/
pthread_mutex_unlock(&bufferLock); //unlock mutex
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
pthread_mutex_lock(&bufferLock); //lock mutex

View File

@ -244,12 +244,22 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex bufferLock
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
//The thread created in initializeHardware is already updating
//OpenPLC's buffers. So this function should do nothing.
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
//The thread created in initializeHardware is already updating
//OpenPLC's buffers. So this function should do nothing.
}

View File

@ -138,10 +138,53 @@ void sendOutput(unsigned char *sendBytes, unsigned char *recvBytes)
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex buffer_lock
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
unsigned char sendBytes[3], recvBytes[6], i;
sendBytes[0] = 0xC2; //read and write IO for both modules
sendBytes[1] = 0; //make sure output is off
sendBytes[2] = 0; //make sure output is off
pthread_mutex_lock(&bufferLock);
for (i=0; i<8; i++)
{
if (bool_output[0][i] != NULL) sendBytes[1] = sendBytes[1] | (*bool_output[0][i] << i); //write each bit
}
for (i=8; i<16; i++)
{
if (bool_output[1][i%8] != NULL) sendBytes[2] = sendBytes[2] | (*bool_output[1][i%8] << (i-8)); //write each bit
}
pthread_mutex_unlock(&bufferLock);
sendOutput(sendBytes, recvBytes);
pthread_mutex_lock(&bufferLock);
//if (int_input[0] != NULL) *int_input[0] = (int)(recvBytes[2] << 8) | (int)recvBytes[3]; //EX
//if (int_input[1] != NULL) *int_input[1] = (int)(recvBytes[4] << 8) | (int)recvBytes[5]; //EY
for (i=0; i<8; i++)
{
if (bool_input[0][i] != NULL) *bool_input[0][i] = (recvBytes[0] >> i) & 0x01;
//printf("%d\t", DiscreteInputBuffer0[i]);
}
for (i=8; i<16; i++)
{
if (bool_input[1][i%8] != NULL) *bool_input[1][i%8] = (recvBytes[1] >> (i-8)) & 0x01;
//printf("%d\t", DiscreteInputBuffer0[i]);
}
//printf("\n");
pthread_mutex_unlock(&bufferLock);
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
unsigned char sendBytes[3], recvBytes[6], i;
sendBytes[0] = 0xC2; //read and write IO for both modules

View File

@ -486,10 +486,10 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex bufferLock
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
pthread_mutex_lock(&bufferLock); //lock mutex
pthread_mutex_lock(&ioLock);
@ -498,6 +498,25 @@ void updateBuffers()
{
if (bool_input[i/8][i%8] != NULL) *bool_input[i/8][i%8] = bool_input_buf[i];
if (int_input[i] != NULL) *int_input[i] = int_input_buf[i];
}
pthread_mutex_unlock(&ioLock);
pthread_mutex_unlock(&bufferLock); //unlock mutex
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
pthread_mutex_lock(&bufferLock); //lock mutex
pthread_mutex_lock(&ioLock);
for (int i = 0; i < MAX_MB_IO; i++)
{
if (bool_output[i/8][i%8] != NULL) bool_output_buf[i] = *bool_output[i/8][i%8];
if (int_output[i] != NULL) int_output_buf[i] = *int_output[i];
}

View File

@ -819,10 +819,10 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex buffer_lock
// must be updated to reflect the actual Input state. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
//lock mutexes
pthread_mutex_lock(&bufferLock);
@ -834,6 +834,30 @@ void updateBuffers()
if (bool_input[i/8][i%8] != NULL) *bool_input[i/8][i%8] = bitRead(InputData.byDigIn, i);
}
//ANALOG IN
uint16_t *analogInputs;
analogInputs = &InputData.wAi0;
for (int i = 0; i < MAX_ANALOG_IN; i++)
{
if (int_input[i] != NULL) *int_input[i] = analogInputs[i];
}
//unlock mutexes
pthread_mutex_unlock(&localBufferLock);
pthread_mutex_unlock(&bufferLock);
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
//lock mutexes
pthread_mutex_lock(&bufferLock);
pthread_mutex_lock(&localBufferLock);
//DIGITAL OUTPUT
for (int i = 0; i < MAX_DIG_OUT; i++)
{
@ -847,14 +871,6 @@ void updateBuffers()
}
}
//ANALOG IN
uint16_t *analogInputs;
analogInputs = &InputData.wAi0;
for (int i = 0; i < MAX_ANALOG_IN; i++)
{
if (int_input[i] != NULL) *int_input[i] = analogInputs[i];
}
//ANALOG OUT
uint16_t *analogOutputs;
uint16_t *pwmOutputs;
@ -875,4 +891,4 @@ void updateBuffers()
//unlock mutexes
pthread_mutex_unlock(&localBufferLock);
pthread_mutex_unlock(&bufferLock);
}
}

View File

@ -36,7 +36,7 @@
#define MAX_INPUT 14
#define MAX_OUTPUT 11
#define MAX_ANALOG_OUT 1
#define MAX_ANALOG_OUT 1
/********************I/O PINS CONFIGURATION*********************
* A good source for RaspberryPi I/O pins information is:
@ -91,10 +91,10 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex buffer_lock
// must be updated to reflect the actual state of the input pins. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
pthread_mutex_lock(&bufferLock); //lock mutex
@ -104,6 +104,18 @@ void updateBuffers()
if (bool_input[i/8][i%8] != NULL) *bool_input[i/8][i%8] = digitalRead(inBufferPinMask[i]);
}
pthread_mutex_unlock(&bufferLock); //unlock mutex
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual state of the output pins. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
pthread_mutex_lock(&bufferLock); //lock mutex
//OUTPUT
for (int i = 0; i < MAX_OUTPUT; i++)
{
@ -118,4 +130,3 @@ void updateBuffers()
pthread_mutex_unlock(&bufferLock); //unlock mutex
}

View File

@ -159,10 +159,22 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex bufferLock
// must be updated to reflect the actual Input state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
// This function here is blank because the thread that connects to the
// Interface program is already filling the OpenPLC buffers with the
// data that is being received.
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex bufferLock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
// This function here is blank because the thread that connects to the
// Interface program is already filling the OpenPLC buffers with the

View File

@ -173,10 +173,10 @@ void initializeHardware()
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual I/O state. The mutex buffer_lock
// must be updated to reflect the actual Input state. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffers()
void updateBuffersIn()
{
//printf("Digital Inputs:\n");
pthread_mutex_lock(&bufferLock); //lock mutex
@ -185,12 +185,6 @@ void updateBuffers()
if (bool_input[i/8][i%8] != NULL) *bool_input[i/8][i%8] = !digitalRead(inputPinMask[i]); //printf("[IO%d]: %d | ", i, !digitalRead(inputPinMask[i]));
}
//printf("\nDigital Outputs:\n");
for (int i = 0; i < MAX_OUTPUT; i++)
{
if (bool_output[i/8][i%8] != NULL) digitalWrite(DOUT_PINBASE + i, *bool_output[i/8][i%8]); //printf("[IO%d]: %d | ", i, digitalRead(DOUT_PINBASE + i));
}
//printf("\nAnalog Inputs:");
for (int i = 0; i < 2; i++)
{
@ -198,7 +192,24 @@ void updateBuffers()
}
//printf("\n");
if(int_output[0] != NULL) pwmWrite(ANALOG_OUT_PIN, *int_output[0]);
pthread_mutex_unlock(&bufferLock); //unlock mutex
}
//-----------------------------------------------------------------------------
// This function is called by the OpenPLC in a loop. Here the internal buffers
// must be updated to reflect the actual Output state. The mutex buffer_lock
// must be used to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateBuffersOut()
{
pthread_mutex_lock(&bufferLock); //lock mutex
//printf("\nDigital Outputs:\n");
for (int i = 0; i < MAX_OUTPUT; i++)
{
if (bool_output[i/8][i%8] != NULL) digitalWrite(DOUT_PINBASE + i, *bool_output[i/8][i%8]); //printf("[IO%d]: %d | ", i, digitalRead(DOUT_PINBASE + i));
}
if(int_output[0] != NULL) pwmWrite(ANALOG_OUT_PIN, *int_output[0]);
pthread_mutex_unlock(&bufferLock); //unlock mutex
}

View File

@ -202,27 +202,31 @@ int main(int argc,char **argv)
printf("WARNING: Failed to lock memory\n");
}
#endif
//gets the starting point for the clock
printf("Getting current time\n");
struct timespec timer_start;
clock_gettime(CLOCK_MONOTONIC, &timer_start);
//======================================================
// MAIN LOOP
//======================================================
for(;;)
{
//make sure the buffer pointers are correct and
//attached to the user variables
glueVars();
pthread_mutex_lock(&bufferLock); //lock mutex
config_run__(tick++);
pthread_mutex_unlock(&bufferLock); //unlock mutex
//gets the starting point for the clock
printf("Getting current time\n");
struct timespec timer_start;
clock_gettime(CLOCK_MONOTONIC, &timer_start);
updateBuffers();
updateTime();
//======================================================
// MAIN LOOP
//======================================================
for(;;)
{
//make sure the buffer pointers are correct and
//attached to the user variables
glueVars();
updateBuffersIn(); //read input image
sleep_until(&timer_start, common_ticktime__);
}
pthread_mutex_lock(&bufferLock); //lock mutex
config_run__(tick++); // execute plc program logic
pthread_mutex_unlock(&bufferLock); //unlock mutex
updateBuffersOut(); //write output image
updateTime();
sleep_until(&timer_start, common_ticktime__);
}
}