RaspberryPi[20] RS422取り込み

某企業からの依頼で、RS422から来るデータと同期をとって2つのパルス取り込の依頼がありました。

実現するための仕様は、2つのパルスのUP DOWNをカウントして、RS422からメッセージが来たときに、メッセージと前回から何回パルスが来たかを同時に記録するという内容です。記録はUSBメモリにしました。RS422の取り込みは、RS422のHATを使用し、パルスはGPIOの割り込みでカウントするという内容です。

ソースコードは以下になります。

#include <stdio.h>      //printf()
#include <stdlib.h>     //exit()
#include <signal.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <unistd.h>
#include "DEV_Config.h"

#define NUM_CNT 10000 // filename change based on NUM_CNT
// Which GPIO pin we're using
#define PIN_OPT 2
#define PIN_ROT 3
// How much time a change must be since the last in order to count as a change
#define IGNORE_CHANGE_BELOW_USEC 10000  //10msec

// Current state of the pin
static volatile int state_opt;
static volatile int state_rot;

// Time of last change
struct timeval last_change_dwn_cnt_opt;
struct timeval last_change_dwn_cnt_rot;


static volatile int  dwn_cnt_opt = 0;
static volatile int  dwn_cnt_rot = 0;
static volatile int  up_cnt_opt = 0;
static volatile int  up_cnt_rot = 0;

time_t t;
FILE *file;
struct tm *local;
unsigned char cfn[255];    
unsigned char buf[255];       
int count = 1;
    
	// Handler for interrupt
void dwn_cnter_opt(void) {
	if((state_opt = digitalRead(PIN_OPT))==0){
		dwn_cnt_opt++;
	}else{
		up_cnt_opt++;
	}	
//	printf("dwn_c:%d up_c:%d\n",dwn_cnt_opt,up_cnt_opt);
	usleep(IGNORE_CHANGE_BELOW_USEC);
}

void dwn_cnter_rot(void) {
	if((state_rot = digitalRead(PIN_ROT))==0){
		dwn_cnt_rot++;
	}else{
		up_cnt_rot++;
	}	
//	printf("dwn_c:%d up_c:%d\n",dwn_cnt_opt,up_cnt_opt);
	usleep(IGNORE_CHANGE_BELOW_USEC);
}
	
void  Handler(int signo)
{
    //System Exit
    printf("\r\nHandler:Program stop\r\n"); 

    DEV_ModuleExit();

    exit(0);
}

void RS485_transmit()
{
    DEV_UART_Init("/dev/ttySC0");
    
    UBYTE pData[100]={0};
    int i=0;
    
    DEV_Digital_Write(RS485EN, 0);
    UART_Write_nByte("Waveshare RS485 RS232 HAT\r\n", 27);
    DEV_Delay_ms(5);//Waiting to send
    DEV_Digital_Write(RS485EN, 1);
    while(1){
            DEV_Digital_Write(RS485EN, 0);
            DEV_Delay_ms(5);//Waiting to send
            DEV_Digital_Write(RS485EN, 1);
    }
}

struct timespec start_time, end_time;
    
void RS485_recieve()
{
	unsigned int sec;
    int nsec;
    float d_sec;

    
    DEV_UART_Init("/dev/ttySC1");
    printf("DEV_UART_Init Passed\r\n");
    
    UBYTE pData[100]={0};
    int i=0;
    int fd;
    int j;
    
	t = time(NULL);
	local = localtime(&t);
	sprintf(cfn,"/media/pi/YTL/rot%02d%02d%02d%02d%04d.txt",local->tm_mon+1,local->tm_mday,local->tm_hour,local->tm_min,count);


    while(1){
		
		pData[i] = UART_Read_Byte();
//		printf("i:%d %c\n",i,pData[i]);
        
        if(pData[i] == '\n')
        {
/* 処理開始後の時間とクロックを取得 */
			clock_gettime(CLOCK_REALTIME, &end_time);
/* 処理中の経過時間を計算 */
			sec = end_time.tv_sec - start_time.tv_sec;
			nsec = end_time.tv_nsec - start_time.tv_nsec;

			d_sec = sec + nsec / (1000.0 * 1000.0 * 1000.0);
		//	printf("end_time.tv_sec:%ld start_time.tv_sec:%ld\n",end_time.tv_sec,start_time.tv_sec);
		//	printf("end_time.tv_nsec:%ld start_time.tv_nsec:%ld\n",end_time.tv_nsec,start_time.tv_nsec);
			
			file = fopen(cfn,"a");	
			printf("CNT:%05d, PST:%f,DCO:%05d,UCO:%05d,DCR:%05d,UCR:%05d,DAT:"
			         ,count,d_sec,dwn_cnt_opt,up_cnt_opt,dwn_cnt_rot,up_cnt_rot);
			
			fprintf(file,"CNT:%05d, PST:%f,DCO:%05d,UCO:%05d,DCR:%05d,UCR:%05d,DAT:"
			         ,count,d_sec,dwn_cnt_opt,up_cnt_opt,dwn_cnt_rot,up_cnt_rot);
			
		
            for(j=0; j<i+1; j++){
				printf("%c",pData[j]);
				fprintf(file,"%c",pData[j]);
			}		
			fclose(file);
//				DEV_Delay_ms(5);//Waiting to send
            i=0;
 /* パルスカウンター リセット */
			  dwn_cnt_opt = 0;
			  dwn_cnt_rot = 0;
			  up_cnt_opt = 0;
			  up_cnt_rot = 0;
			  count++;
			  
 /* 処理開始前の時間を取得 */			  			  
			clock_gettime(CLOCK_REALTIME, &start_time);         
        }
        else if(i>100)
        {
            i=0;
        }
        else
        {
            i++;
        }
    }
}

int main(int argc, char **argv)
{
		// Init
	wiringPiSetup();
	
	// Set pin to output in case it's not
	pinMode(PIN_OPT, INPUT);
	pinMode(PIN_ROT, INPUT);
	pullUpDnControl(PIN_OPT, PUD_UP);
	pullUpDnControl(PIN_ROT, PUD_UP);


	// Bind to interrupt
	wiringPiISR(PIN_OPT, INT_EDGE_BOTH, &dwn_cnter_opt); // BOTH or FALLING or RISING
	wiringPiISR(PIN_ROT, INT_EDGE_BOTH, &dwn_cnter_rot); // BOTH or FALLING or RISING

	// Get initial state of pin
	state_opt = digitalRead(PIN_OPT);
	state_rot = digitalRead(PIN_ROT);


	printf("state_opt:%d state_rot:%d\n",state_opt,state_rot);
	count = 1;
	printf("version 1.02\n");
    // Exception handling:ctrl + c
    signal(SIGINT, Handler);
    
	if (DEV_ModuleInit()==1)return 1;
    
    // RS485_UART();
    RS485_recieve();

	DEV_ModuleExit();
    return 0; 
}