2017年7月24日 星期一

[語言工具箱] C Linux queue.h之TAILQ序列實作

make_i2c_message->產生訊息並塞到queue.

i2c_tx_check(每300ms檢查一次) -> send_rf_cmd() ->

=============================================================
infoManager.c

static timer g_sendi2c_timer;

TAILQ_HEAD(i2c_tx_queue, i2c_tx_message);
struct i2c_tx_queue *tx_q = NULL;
#define RF_WKUP_MAIN 129//ENET0_MDIO bank4 pin1



int send_rf_cmd(struct i2c_tx_message *msg)
{
    int ret = 1;
    switch(msg->id)
    {
             .....中間略過......
    }
    return ret;
}

.................中間略過.................

void* i2c_tx_check(void* unused)
{
    int ret = 0;
    uint32_t fob_status;
    struct i2c_tx_message *m2 = NULL;
    ret = gpio_get_value(RF_WKUP_MAIN, &fob_status);
    //printf("[Gerald] RF_WKUP_MAIN = %d\n", fob_status);

    if(ret > 0)//errno
    {
        IM_DBG_ERROR("read RF_WKUP_MAIN failed, ret = %d", ret);
        return;
    }
    if((!TAILQ_EMPTY(tx_q)) && (fob_status == 1))//high: ready; low: busy
    {
        m2 = TAILQ_FIRST(tx_q);
        ret = send_rf_cmd(m2);
        TAILQ_REMOVE(tx_q, m2, node);
        free(m2);
    }
}


void start_checker_timer()
 {
    .................中間略過.................
    timer_setup(&g_sendi2c_timer);
     .................中間略過.................
    g_sendi2c_timer.set_timer(&g_sendi2c_timer, 300, true, i2c_tx_check, NULL);
 }


void stop_checker_timer()
 {
    .................中間略過.................
    g_sendi2c_timer.cancel(&g_sendi2c_timer);
 }

void init_i2c_tx_queue()
{
    tx_q = malloc(sizeof(*tx_q));
    TAILQ_INIT(tx_q);
    gpio_export(RF_WKUP_MAIN);
    gpio_dir_in(RF_WKUP_MAIN);
}

void uninit_i2c_tx_queue()
{
    free(tx_q);
}

void make_i2c_message(enum rf_command_table id, char *cmd)
{
    struct i2c_tx_message *m1 = NULL;
    m1 = calloc(1, sizeof(*m1));
    if(m1 == NULL)
    {
        IM_DBG_ERROR("Can not allocate i2c cmd\n");
    }
    else
    {
        m1->id = id;
        m1->cmd = cmd;
        TAILQ_INSERT_TAIL(tx_q, m1, node);
        DKEY_BMW_PROFILE_LOG("cmd_id = %d, value = %s", m1->id, m1->cmd);
    }
}



void initInfoManager() {
      .................中間略過.................
    infoMgr->make_i2c_message = make_i2c_message;
     .................中間略過.................
    init_i2c_tx_queue();
 }

void uninitInfoManager() {
     .................中間略過.................
    uninit_i2c_tx_queue();
     .................中間略過.................
}
==============================================================
infoManager.h

#include <sys/queue.h>


enum rf_command_table {
    MASTER_STATE             = 1,
    ACCESS                   = 2,
    WINDOW                   = 3,
    MISCELLANEOUS            = 4,
    AUTO_DRIVING             = 5,
    VEHICLE_FACILITY_CONTROL = 6,
};

struct i2c_tx_message
{
    enum rf_command_table id;
    char *cmd;
    TAILQ_ENTRY(i2c_tx_message) node;
};

 typedef struct infoManager_s {
     .................中間略過.................
    void (*make_i2c_message)();

 } infoManager;


void add_language_change_event_notify(enum im_evnet_category_t category, int eve
 .................中間略過.................
int send_rf_cmd(struct i2c_tx_message *msg);
========================================================

結論 :























==============================================================

[語言工具箱] C 語言的檔案處理 OPEN / FOPEN


[Open]
#include  //fcntl.h - file control options
Open 有兩種型態 : 
int open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);

以下範例表達 : 
int fd;//宣告int型態的file open狀態容器
char buff[1024];
打開的用法fd = open("filename", 權限);
//filename 在Linux driver中,通常是上層用來做device node的開啟 ->   /sys/..../device_node
假設開啟成功 fd = 0 ,如果失敗 => 小於0 或負數(返回值:成功return 0,出現錯誤return -1並設置errno)

write(fd, );
1 = read(fd1,buff,sizeof(buff))) > 0);
//read 等於1 代表大小大於0‧ 還有值 可以繼續讀取,通常用於while迴圈‧
close(fd); //(返回值:成功return 0,出現錯誤return -1並設置errno)

權限一覽表 : 
O_RDONLY開啟檔案(唯讀).
O_WRONLY開啟檔案(唯寫).
O_RDWR開啟檔案(可被讀跟寫).
O_APPENDAppend new information to the end of the file.
O_TRUNCInitially clear all data from the file.
O_CREAT如果未存在這個檔案,那就建立這個檔案‧
O_EXCLCombined with the O_CREAT option, it ensures that the caller must create the file. If the file already exists, the call will fail.
reference : http://www.thegeekstuff.com/2010/10/linux-error-codes
ERROR CODE TABLE(errno table)
Error numberError CodeError Description
1EPERMOperation not permitted
2ENOENTNo such file or directory
3ESRCHNo such process
4EINTRInterrupted system call
5EIOI/O error
6ENXIONo such device or address
7E2BIGArgument list too long
8ENOEXECExec format error
9EBADFBad file number
10ECHILDNo child processes
11EAGAINTry again
12ENOMEMOut of memory
13EACCESPermission denied
14EFAULTBad address
15ENOTBLKBlock device required
16EBUSYDevice or resource busy
17EEXISTFile exists
18EXDEVCross-device link
19ENODEVNo such device
20ENOTDIRNot a directory
21EISDIRIs a directory
22EINVALInvalid argument
23ENFILEFile table overflow
24EMFILEToo many open files
25ENOTTYNot a typewriter
26ETXTBSYText file busy
27EFBIGFile too large
28ENOSPCNo space left on device
29ESPIPEIllegal seek
30EROFSRead-only file system
31EMLINKToo many links
32EPIPEBroken pipe
33EDOMMath argument out of domain of func
34ERANGEMath result not representable
35EDEADLKResource deadlock would occur
36ENAMETOOLONGFile name too long
37ENOLCKNo record locks available
38ENOSYSFunction not implemented
39ENOTEMPTYDirectory not empty
40ELOOPToo many symbolic links encountered
42ENOMSGNo message of desired type
43EIDRMIdentifier removed
44ECHRNGChannel number out of range
45EL2NSYNCLevel 2 not synchronized
46EL3HLTLevel 3 halted
47EL3RSTLevel 3 reset
48ELNRNGLink number out of range
49EUNATCHProtocol driver not attached
50ENOCSINo CSI structure available
51EL2HLTLevel 2 halted
52EBADEInvalid exchange
53EBADRInvalid request descriptor
54EXFULLExchange full
55ENOANONo anode
56EBADRQCInvalid request code
57EBADSLTInvalid slot
59EBFONTBad font file format
60ENOSTRDevice not a stream
61ENODATANo data available
62ETIMETimer expired
63ENOSROut of streams resources
64ENONETMachine is not on the network
65ENOPKGPackage not installed
66EREMOTEObject is remote
67ENOLINKLink has been severed
68EADVAdvertise error
69ESRMNTSrmount error
70ECOMMCommunication error on send
71EPROTOProtocol error
72EMULTIHOPMultihop attempted
73EDOTDOTRFS specific error
74EBADMSGNot a data message
75EOVERFLOWValue too large for defined data type
76ENOTUNIQName not unique on network
77EBADFDFile descriptor in bad state
78EREMCHGRemote address changed
79ELIBACCCan not access a needed shared library
80ELIBBADAccessing a corrupted shared library
81ELIBSCN.lib section in a.out corrupted
82ELIBMAXAttempting to link in too many shared libraries
83ELIBEXECCannot exec a shared library directly
84EILSEQIllegal byte sequence
85ERESTARTInterrupted system call should be restarted
86ESTRPIPEStreams pipe error
87EUSERSToo many users
88ENOTSOCKSocket operation on non-socket
89EDESTADDRREQDestination address required
90EMSGSIZEMessage too long
91EPROTOTYPEProtocol wrong type for socket
92ENOPROTOOPTProtocol not available
93EPROTONOSUPPORTProtocol not supported
94ESOCKTNOSUPPORTSocket type not supported
95EOPNOTSUPPOperation not supported on transport endpoint
96EPFNOSUPPORTProtocol family not supported
97EAFNOSUPPORTAddress family not supported by protocol
98EADDRINUSEAddress already in use
99EADDRNOTAVAILCannot assign requested address
100ENETDOWNNetwork is down
101ENETUNREACHNetwork is unreachable
102ENETRESETNetwork dropped connection because of reset
103ECONNABORTEDSoftware caused connection abort
104ECONNRESETConnection reset by peer
105ENOBUFSNo buffer space available
106EISCONNTransport endpoint is already connected
107ENOTCONNTransport endpoint is not connected
108ESHUTDOWNCannot send after transport endpoint shutdown
109ETOOMANYREFSToo many references: cannot splice
110ETIMEDOUTConnection timed out
111ECONNREFUSEDConnection refused
112EHOSTDOWNHost is down
113EHOSTUNREACHNo route to host
114EALREADYOperation already in progress
115EINPROGRESSOperation now in progress
116ESTALEStale NFS file handle
117EUCLEANStructure needs cleaning
118ENOTNAMNot a XENIX named type file
119ENAVAILNo XENIX semaphores available
120EISNAMIs a named type file
121EREMOTEIORemote I/O error
122EDQUOTQuota exceeded
123ENOMEDIUMNo medium found
124EMEDIUMTYPEWrong medium type
125ECANCELEDOperation Canceled
126ENOKEYRequired key not available
127EKEYEXPIREDKey has expired
128EKEYREVOKEDKey has been revoked
129EKEYREJECTEDKey was rejected by service
130EOWNERDEADOwner died
131ENOTRECOVERABLEState not recoverable

=============================================
[Fopen]

#include

FOPEN : FILE * fopen(const char * path,const char * mode); 
Example : 
FILE *input;                                                                                                                    
input=fopen(FILE_PATH,"r");
if ( input==NULL ) 
{
    fprintf(stderr, "Open file:%s fail!", FILE_PATH);
    return;
}


FCLOSE : int result fclose(FILE*);
Example : 
input = fopen(FILE_PATH,"r");
fclose(input);


FREAD : fread(void *buffer,int num_byte,int count,FILE *fp);
Example : 
FILE *input;
int result;
char * buffer;
input = fopen(FILE_PATH,"r"); 
if ( input == NULL ) 
     fprintf(stderr, "Open file:%s fail!", FILE_PATH); 
     return; 
result = fread (buffer,1, Size,input ); 
if (result == -1) 
{
    printf("File read error!!!"); 
    fclose (pFile); 
    return -1; 
fclose (input); 
return 0;

  


FWRITE : fwrite(void *buffer,int num_byte,int count,FILE *fp);
Example : 



FSCANF : fscanf(FILE *fp, constchar* format, [argument ... ]);
用途 : 從檔案讀取數據到宣告的容器中。 
Retrun type : 回傳讀入個數,錯誤回傳-1(EOF)。  
Example :                                                                                                               

int main(void)

{

    char a1[20], a2[20];

    FILE *input;

    input=fopen(FILE_PATH,"r");

    if (input==NULL) 

    {

        fprintf(stderr, "Open file:%s fail!", FILE_PATH);

        return -1;

    }

    fscanf(input, "%s%s", a1, a2);

    fclose(input);

    printf("%s %s\n", a1, a2);

    return 0;

}


FSEEK : 


FPRINTF :  



Extend from : ext2_io.h
Type : Embeded C
OPEN
int write_device_node(char* node, char* value)
{
  int fd = open(node, O_RDWR);
  if(fd<0 nbsp="" p="">  {
          printf("open %s for write failed\n", node);
          return -1;
   }
    int ret = write(fd, value, strlen(value));
    close(fd);
    return ret;
}

2017年7月23日 星期日

[IoT 終端裝置應用] Arduino 步進馬達實作

首先要先感謝 http://engyfun.blogspot.tw/2015/02/here-is-source-code-for-our-28byj48.html 所提供的ULN2003 driver library source code

Arduino的driver header and Cpp 檔案可以放到如下之位置






















路徑是在你安裝Arduino的資料夾裡的\libraries,資料夾名稱可以自己命名,完成之後便可以在Arduino裡看到我們剛剛丟進去的driver並且匯入使用了
























這時候我們就可以在我們的Arduino code裡面使用#include <StepperMotor.h>
來使用我們剛剛的driver了


Arduino code 如下
主要功能為可以由console輸入需要旋轉的角度以及輸出旋轉角度,完成之後回復原狀
==================================================================
#include <StepperMotor.h>
// ULN2003 Motor Driver
StepperMotor motor(8,9,10,11);// IN1, IN2, IN3, IN4
float Speed = 2.0; // motor gets slower as this number increases
float Steps = 4076.0; // 4076 is approx 360 degrees
// maximum speed about 15RPM at 5 volts with an Arduino
float Delay = 1000.0; // delay in ms for next round
float n ; //dgree of motor 
String inString = ""; // string to hold input
#define led 13 // onboard led

void setup(){
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW); // turn off LED
  motor.setStepDuration(Speed);
}

void loop(){
  // motor turn clockwise
  digitalWrite(led, HIGH); 
  inString = "";// clean forword input
  while (Serial.available() > 0) {
    int inChar = Serial.read();
    if (inChar != '\n') { 
      // As long as the incoming byte
      // is not a newline,
      // convert the incoming byte to a char
      // and add it to the string
      inString += (char)inChar;
    }
    n = inString.toFloat();
  }
  Serial.print("turn clockwise degree:");
  Serial.println(n);
  motor.step(Steps*n/360.0);
  delay(Delay);
  // reverse motor
  digitalWrite(led, LOW); // shows reverse rotation
  Serial.print("turn clockwise degree:");
  Serial.println(-n);
  motor.step(-Steps*n/360.0);
  delay(Delay);

}

==================================================================