2017년 8월 22일 화요일

[3] 각 하드웨어를 연결할 수 있는 모듈 만들기(1) – 스캔 파형 신호 생성 방법(라즈베리파이 코드)

4. 라즈베리 파이 프로그래밍

라즈베리파이 코드를 테스트 해야 한다.

1.png

여기서 아두이노의 s_p_signal에 따라서 라즈베리파이가 동기화 되는 것이 가장 중요하다. 그래서 우선 라즈베리파이에서 동기화 되어서 한 프레임의 이미지를 만드는 함수인 ReadoneFrame()함수를 빼고 잘 동작하는 지 테스트를 해보았다.
원래는 ReadoneFrame() 함수에서 배열에 영상 테이터를 읽어들여서 이것은 텍스트 파일로 만드는 방식인데 이 함수를 뺐기때문에 배열 값을 확인할 수 있도록 초기화시킨뒤 텍스트 파일로 이 값들이 텍스트 파일로 만들어 지는 지 확인하였다.
배열의 크기는 1000*512이다.
결과 텍스트 파일 imageData.txt
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <wiringPi.h>

#define ARDUINO_ENABLE_PIN 26 //BCM 12
#define ARDUINO_S_P_SIGNAL_PIN 7 //BCM 4

#define GPIO_BASE 0x3F200000
#define GPLEV0 0x34

#define ENABLE 0
#define DISABLE 1
#define FRAME_NUMBER 1
#define MAXROW 512
#define MAXCOL 1000
#define DELAYSECOND 10
#define START 0
#define STOP 1

int s_p_signal = STOP;
volatile unsigned int* gpio;

void setEnable(int command);
void ReadOneFrame(char (*oneFrame)[MAXCOL]);
void printData(char (*oneFrame)[MAXCOL], int n);
void initialize_interrupt();
void initialize_wiringPi();
void initialize_8bit_parallel_GPIO();
char read8bitData();
void s_p_signal_state_START();
void s_p_signal_state_STOP();
void initialize_imageArr(char (*oneFrame)[MAXCOL]);

int main(void)
{
char image[MAXROW][MAXCOL];
int count=0;

setEnable(DISABLE);
initialize_8bit_parallel_GPIO();
initialize_wiringPi();
initialize_interrupt();
initialize_imageArr(image);

for(count=0; count<FRAME_NUMBER; count++){
setEnable(ENABLE);
//ReadOneFrame(image);
setEnable(DISABLE);
printData(image, count);
delay(DELAYSECOND*1000);
}

return 0;

}

void initialize_imageArr(char (*oneFrame)[MAXCOL]){
int i, j, val=0, method;

for(i=0; i<MAXROW; i++){
for(j=0; j<MAXCOL; j++){
oneFrame[i][j] = val;
}
val++;
}
}

void s_p_signal_state_START(){
s_p_signal = START;
}

void s_p_signal_state_STOP(){
s_p_signal = STOP;
}

void initialize_interrupt(){
if(wiringPiISR(ARDUINO_S_P_SIGNAL_PIN, INT_EDGE_FALLING, &s_p_signal_state_START)<0){
printf("Unable to setup ISR\n");
exit(-1);
}

if(wiringPiISR(ARDUINO_S_P_SIGNAL_PIN, INT_EDGE_RISING, &s_p_signal_state_START)<0){
printf("Unable to setup ISR\n");
exit(-1);
}
}

void initialize_wiringPi(){
if(wiringPiSetup() == -1){
printf("failed wiringPi");
       exit(-1);
}

pinMode(ARDUINO_ENABLE_PIN, OUTPUT);
}

void initialize_8bit_parallel_GPIO(){
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if(fd<0){
         printf("can't open /dev/mem \n");
         exit(-1);
     }

     char *gpio_memory_map = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);

     if(gpio_memory_map == MAP_FAILED){
         printf("ERROR: mmap\n");
 exit(-1);
 }
 
 gpio = (volatile unsigned int*)gpio_memory_map;
}

void setEnable(int command){
if(command == ENABLE){
digitalWrite(ARDUINO_ENABLE_PIN, ENABLE);
}else if(command == DISABLE){
digitalWrite(ARDUINO_ENABLE_PIN, DISABLE);
}

}

char read8bitData(){
int input = gpio[GPLEV0/4] & (0xFF<<16);

input = input >> 16;
input = input & 0xFF;

return (char) input;

}

void ReadOneFrame(char (*oneFrame)[MAXCOL]){
int row = 0, i=0;

for(row=0; row<MAXROW; row++){
while(s_p_signal == STOP);//wait

for(i=0; i<MAXCOL; i++){
oneFrame[row][i] = read8bitData();
if (s_p_signal == STOP) //interrupt
break;
}

}
}

//http://dream-cy.tistory.com/47
void printData(char (*oneFrame)[MAXCOL], int n){
FILE* wfp = fopen("imageData", "w");
int i=0, j=0;

fprintf(wfp, "image[%d]\n", n);
for(i=0; i<MAXROW; i++){
for(j=0; j<MAXCOL; j++){
fprintf(wfp, "%d  ", oneFrame[i][j]);

리눅스 실행 명령어
gcc -o main main.c -lwiringPi
sudo ./main

4. 아두이노 듀와 라즈베리파이 동기화 시키기
- 라즈베리파이 인터럽트 테스트

인터럽트는 wiringPi 라이브러리를 썼는 데 이 함수가 IRQ나 FIQ 인터럽트 방식이 아닌 것 같다. 인터럽트를 disable시키기 위해서 IRQ와 FIQ 인터럽트가 일어나지 못하게 ARM의 CPSR에 설정을 했는 데 disable이 안됐다.
7.png
8.png
arm의 내부 레지스터를 건드리는 코드는 다음과 같았음.
.globl enable
.globl disable

enable:
.func enable
mrs r0, cpsr
bic r0, r0, 0xC0
msr cpsr_c, r0
mov pc, lr
.endfunc

disable:
.func disable
mrs r0, cpsr
orr r0, r0, 0xC0
msr cpsr_c, r0
mov pc, lr
.endfunc

이게 인터럽트 disable을 못 시켜서 다른 방식으로 강제로 gpio 감지를 못하게 하는 방식을 썼다.
[Register View]
44.png

다음의 의 데이터시트를 보면 GPREN과 GPFEN의 비트가 0이면 gpio의 falling와 rising edge가 disable된다.
그래서 코드에서 disable()함수를 쓰면 인터럽트가 안일어나고 enable()을 쓰면 인터럽트가 일어나게 하였다.
55.png
66.png

[코드]
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

#define GPIO_BASE 0x3F200000
#define GPREN0 0x4C
#define GPREN1 0x50
#define GPFEN0 0x58
#define GPFEN1 0x5C
#define GPEDS0 0x40
#define GPEDS1 0x44

#define S_P_SIGNAL_PIN 7

volatile unsigned int* gpio;

void disable();
void enable();
void initialize_8bit_parallel_GPIO();
void startISR(void);
void initialize_interrupt();
void initialize_wiringPi();

int main(void) {
initialize_8bit_parallel_GPIO();
disable();
initialize_wiringPi();
initialize_interrupt();

 while ( 1 ) {
   printf("------disable interrupt------\n");
disable();
delay(1000);
printf("-------enable interrupt-------\n");
enable();
delay(1000);
 }

 return 0;
}

void disable(){
gpio[GPFEN0/4] = (0x00000000);
gpio[GPFEN1/4] = (0x00000000);
gpio[GPREN0/4] = (0x00000000);
gpio[GPREN1/4] = (0x00000000);
}

void enable(){
gpio[GPFEN0/4] = (0xFFFFFFFF);
gpio[GPFEN1/4] = (0xFFFFFFFF);
gpio[GPREN0/4] = (0xFFFFFFFF);
gpio[GPREN1/4] = (0xFFFFFFFF);
}
void initialize_8bit_parallel_GPIO(){
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if(fd<0){
         printf("can't open /dev/mem \n");
         exit(-1);
     }

     char *gpio_memory_map = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);

     if(gpio_memory_map == MAP_FAILED){
         printf("ERROR: mmap\n");
 exit(-1);
 }
 
 gpio = (volatile unsigned int*)gpio_memory_map;
}

void startISR(void) {
char val = digitalRead(S_P_SIGNAL_PIN);
if(val == LOW)
printf("falling edge detected\n");
else if(val == HIGH)
printf("rising edge detected\n");
}

void initialize_interrupt(){
pinMode(S_P_SIGNAL_PIN, INPUT);
pullUpDnControl(S_P_SIGNAL_PIN, PUD_UP);

if ( wiringPiISR (S_P_SIGNAL_PIN, INT_EDGE_BOTH, &startISR) < 0 ) {
     fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno));
     exit(-1);
}

}

void initialize_wiringPi(){
if (wiringPiSetup () < 0) {
     fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno));
     exit(-1);
 }

}

[외부 신호]
외부 신호는 아두이노를 이용하여 200ms주기의 펄스파를 주었다.
#define PIN 53

void setup(){
 pinMode(PIN, OUTPUT);
}

void loop(){
   digitalWrite(PIN, HIGH);
   delay(100);
   digitalWrite(PIN, LOW);
   delay(100);
}

[결과]
10.png
disable()함수가 실행되고 있는 1초 동안에는 인터럽트가 발생하지 않는 것을 확인 할 수 있다. 그리고 enable()함수가 실행되면 인터럽트가 실행된다. 1초 동안에 200ms 펄스는 5개 있기때문에 rising_falling이 5번 나타나는 것을 알 수 있다.

5. 라즈베리 파이에서 이미지를 만드는 함수 구현
[핀 연결]
아두이노 s_p_signal 핀(2)과 라즈베리파이 s_p_signal 핀 연결(BCM 4)
여기에 오실로스코프로 측정하였음.
아두이노 enable 핀(13/12)는 GND에 연결
라즈베리파이 8bit 병렬 핀(BCM 16~23)에서 상위 4비트는 GND에 하위 4비트는 VCC에 연결

[코드]
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <wiringPi.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>

//PIN NUMBER
#define ARDUINO_ENABLE_PIN 26 //BCM 12
#define S_P_SIGNAL_PIN 7 //BCM4

//rapberry pi register
#define GPIO_BASE 0x3F200000
#define GPLEV0 0x34
#define GPREN0 0x4C
#define GPREN1 0x50
#define GPFEN0 0x58
#define GPFEN1 0x5C
#define GPEDS0 0x40
#define GPEDS1 0x44

//set value
#define ENABLE 0
#define DISABLE 1
#define FRAME_NUMBER 1
#define MAXROW 512
#define MAXCOL 1000
#define DELAYSECOND 10
#define START 0
#define STOP 1

int s_p_signal = STOP;
volatile unsigned int* gpio;

void disable();
void enable();
void interruptSR(void);
void setEnable(int command);
void ReadOneFrame(char (*oneFrame)[MAXCOL]);
void printData(char (*oneFrame)[MAXCOL], int n);
void initialize_interrupt();
void initialize_wiringPi();
void initialize_8bit_parallel_GPIO();
char read8bitData();
void s_p_signal_state_START();
void s_p_signal_state_STOP();
void initialize_imageArr(char (*oneFrame)[MAXCOL]);

int main(void)
{
char image[MAXROW][MAXCOL];
int count=0;

setEnable(DISABLE);
initialize_8bit_parallel_GPIO();
disable();
initialize_wiringPi();
initialize_interrupt();
initialize_imageArr(image);

for(count=0; count<FRAME_NUMBER; count++){

setEnable(ENABLE);
ReadOneFrame(image);
setEnable(DISABLE);
printf("makeing image...\n");
printData(image, count);
delay(DELAYSECOND*1000);
}
printf("program end\n");
return 0;

}

void disable(){
gpio[GPFEN0/4] = (0x00000000);
gpio[GPFEN1/4] = (0x00000000);
gpio[GPREN0/4] = (0x00000000);
gpio[GPREN1/4] = (0x00000000);
}


void enable(){
gpio[GPFEN0/4] = (0xFFFFFFFF);
gpio[GPFEN1/4] = (0xFFFFFFFF);
gpio[GPREN0/4] = (0xFFFFFFFF);
gpio[GPREN1/4] = (0xFFFFFFFF);
}

void initialize_imageArr(char (*oneFrame)[MAXCOL]){
int i, j, val=0, method;

for(i=0; i<MAXROW; i++){
for(j=0; j<MAXCOL; j++){
oneFrame[i][j] = val;
}
//val++;
}
}

void s_p_signal_state_START(){
s_p_signal = START;
}

void s_p_signal_state_STOP(){
s_p_signal = STOP;
}

void initialize_interrupt(){
pinMode(S_P_SIGNAL_PIN, INPUT);
pullUpDnControl(S_P_SIGNAL_PIN, PUD_UP);

if ( wiringPiISR (S_P_SIGNAL_PIN, INT_EDGE_BOTH, &interruptSR) < 0 ) {
     fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno));
     exit(-1);
}

}

void initialize_wiringPi(){
if(wiringPiSetup() == -1){
printf("failed wiringPi");
       exit(-1);
}

pinMode(ARDUINO_ENABLE_PIN, OUTPUT);
}

void initialize_8bit_parallel_GPIO(){
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if(fd<0){
         printf("can't open /dev/mem \n");
         exit(-1);
     }

     char *gpio_memory_map = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);

     if(gpio_memory_map == MAP_FAILED){
         printf("ERROR: mmap\n");
 exit(-1);
 }
 
 gpio = (volatile unsigned int*)gpio_memory_map;
}

void setEnable(int command){
if(command == ENABLE){
digitalWrite(ARDUINO_ENABLE_PIN, ENABLE);
}else if(command == DISABLE){
digitalWrite(ARDUINO_ENABLE_PIN, DISABLE);
}

}

char read8bitData(){
int input = gpio[GPLEV0/4] & (0xFF<<16);

input = input >> 16;
input = input & 0xFF;

return (char) input;

}

void ReadOneFrame(char (*oneFrame)[MAXCOL]){
int row = 0, i=0;

enable();
for(row=0; row<MAXROW; row++){
while(s_p_signal == STOP);//wait

for(i=0; i<MAXCOL; i++){
oneFrame[row][i] = read8bitData();
if (s_p_signal == STOP) //interrupt
break;
}

}
disable();
}

//referrence: http://dream-cy.tistory.com/47
void printData(char (*oneFrame)[MAXCOL], int n){
FILE* wfp = fopen("imageData", "w");
int i=0, j=0;

fprintf(wfp, "image[%d]\n", n);
for(i=0; i<MAXROW; i++){
for(j=0; j<MAXCOL; j++){
fprintf(wfp, "%d  ", oneFrame[i][j]);
}
fprintf(wfp, "\n--------------------------------------------------------------------------------------------------------------------------------------------------\n");
}

}

void interruptSR(void) {
char val = digitalRead(S_P_SIGNAL_PIN);
if(val == LOW){
s_p_signal = START;
// printf("falling edge detected\n");
}
else if(val == HIGH){
s_p_signal = STOP;
// printf("rising edge detected\n");
}
}

[결과]
88.png
프로그램이 시작하지마자 making image...글자가 나오는데 program end..는 한 5초 뒤에 나오는 것 같다. 배열을 텍스트로 만드는 게 오래걸리는 듯.

20161029_185708.jpg

댓글 없음:

댓글 쓰기

clear images were obtained