About this Article
Cubieboard series have good support for 1-wire devices. In this tutorial, the whole procedure of connecting DS18B20 thermal sensor to Cubieboard(or Cubieboard2) is introduced, including kernel configuration, GPIO configuration, device access. As for DS18B20 details, please refer the data sheet: http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf.
Make certain that the kernel has been configed properly, as follows.
Device Drivers ---> [*] GPIO Support ---> <*> GPIO Support for sunxi platform <*> Dallas's 1-wire support ---> <*> 1-wire sunxi support 1-wire Bus Masters ---> <*> GPIO 1-wire busmaster 1-wire Slaves ---> <*> Thermal family implementation
You can also compile these as modules as you like, and the generated modules are gpio_sunxi, w1_sunxi, w1_gpio, w1_slave_therm.
The kernel documents have some introduction to 1-w support, you may look into it. What we should do is making 1-w support functional in script.bin. So, edit the script.fex, modify some rows like this:
[gpio_para] gpio_used = 1 gpio_num = 31 ... gpio_pin_28 = port:PB10<0><default><default><0> ... [w1_para] gpio = 28
You can choose any other GPIO expansion pins as a 1-w pin, but do remember set it both in gpio_para and w1_para sections. After that, generate the script.bin
root@CB:/boot/ # cp script.bin script.bin.ori root@CB:/boot/ # fex2bin script.fex script.bin
Then, you can reboot your Cubieboard now.
DS18B20's connection is quite easy. Take the external power supply method for example, DS18B20's Vdd & Gnd pins will be connected to Cubieboard's Vcc(both 3.3v and 5.0v will be fine) & Gnd respectively, and the signal pin will be connected to the expansion pin defined in the script.fex, say, PB10(refer this:http://docs.cubieboard.org/products/a10_cubieboard/expansion_ports). And don's forget add a pull-up 4.7KΩ resistor between the signal pin and Vdd.
The following code fetch temperature data from a DS18B20 in every 5 seconds, together with current localtime, and display on a 8-digits 8-segments common anode LED-displayer. This code piece depends on Cubieboard GPIO Library, you can download it here.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <signal.h> #include <pthread.h> #include "gpio_lib.h" #define LSBFIRST 0 #define MSBFIRST 1 #define DISPBUF_LEN 8 typedef unsigned char byte; // w1-thermal(DS18B20) device file, change it in your case. const char* DS18B20_DEVICE="/sys/bus/w1/devices/28-000004f0230d/w1_slave"; /* * 74HC595 relative stuff */ // Cubieboard pin connected to ST_CP of 74HC595 (RCK) unsigned int latchPin = SUNXI_GPB(11); // Cubieboard pin connected to SH_CP of 74HC595 (SCK) unsigned int clockPin = SUNXI_GPB(13); // Cubieboard pin connected to DS of 74HC595 (DIN) unsigned int dataPin = SUNXI_GPH(7); /* * Display relative stuff */ // Digits: "0,1,2,....,9" for common anode 8-segment-LED unsigned int digit_tab[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; // Digits with a 'dot' at the right-bottom corner unsigned int digitdot_tab[] = { 0xc0&0x7f, 0xf9&0x7f, 0xa4&0x7f, 0xb0&0x7f, 0x99&0x7f, 0x92&0x7f, 0x82&0x7f, 0xf8&0x7f, 0x80&0x7f, 0x90&0x7f}; // Symbols: 'clear', 'dot', '-' unsigned int symbol_tab[]={ 0xff, 0x7f, 0xbf}; // LED display buffer static char dispbuf[DISPBUF_LEN]; /** * Set Cubieboard's GPIO port-D pin I/O mode: INPUT/OUTPUT */ void pinMode(unsigned int pin, unsigned int io_mode) { if (SETUP_OK != sunxi_gpio_set_cfgpin(pin, io_mode)) { printf("Failed to config GPIO pin\n"); } } /** * Set Cubieboard's GPIO port-D pin value(LOW/HIGH) */ void digitalWrite(int pin, int hl) { if (sunxi_gpio_output(pin, hl)) { printf("Failed to set GPIO pin value\n"); } } /** * Arduino shiftOut: * https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring_shift.c */ void shiftOut(unsigned int dataPin, unsigned int clockPin, int bitOrder, byte val) { byte i; for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) digitalWrite(dataPin, ! !(val & (1 << i))); else digitalWrite(dataPin, ! !(val & (1 << (7 - i)))); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } } /** * Initialize the GPIO & relative pins */ void init_gpio() { if (SETUP_OK != sunxi_gpio_init()) { printf("Failed to initialize GPIO\n"); } pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } /** * Get current temperature from the w1-thermal device */ void get_temperature(char* tempbuf, int len) { char* line=NULL; char* temperature_tok=NULL; int temperature=0; int n; // open the thermal sensor's device FILE* fp=fopen(DS18B20_DEVICE,"r"); if(!fp){ fprintf(stderr,"Failed to open device(%s) file!\n", DS18B20_DEVICE); return; } fseek(fp,0,SEEK_SET); // skip the first line getline(&line, &n, fp); free(line); line=NULL; // get the temperature line getline(&line, &n, fp); printf("line:%s\n",line); strtok(line,"="); temperature_tok=strtok(NULL,"="); if(temperature_tok){ strncpy(tempbuf, temperature_tok, len); } free(line); fclose(fp); } /** * Thread of filling the time infomation into display buffer */ void* time_to_dispbuf() { time_t timep; struct tm *p; char timebuf[4]; int interval=1; // in seconds while(1){ // get localtime time(&timep); p = localtime(&timep); sprintf(timebuf, "%02d%02d", p->tm_hour, p->tm_min); dispbuf[0]=digit_tab[timebuf[0] - '0']; dispbuf[1]=digitdot_tab[timebuf[1] - '0']; dispbuf[2]=digit_tab[timebuf[2] - '0']; dispbuf[3]=digit_tab[timebuf[3] - '0']; dispbuf[4]=symbol_tab[2]; // '-' sleep(interval); } } /** * Thread of filling the temperature into display buffer */ void* temp_to_dispbuf() { char tempbuf[3]; int interval=5; // in seconds; while(1){ memset(tempbuf,0, sizeof tempbuf); get_temperature(tempbuf, sizeof tempbuf); printf("temp:%c%c%c\n", tempbuf[0], tempbuf[1], tempbuf[2]); // check temperature validity if(isdigit(tempbuf[0]) && isdigit(tempbuf[1]) && isdigit(tempbuf[2])){ dispbuf[5]=digit_tab[tempbuf[0]-'0']; dispbuf[6]=digitdot_tab[tempbuf[1]-'0']; dispbuf[7]=digit_tab[tempbuf[2]-'0']; } sleep(interval); } } int main(int argc, char **argv) { pthread_t get_time_thread, get_temp_thread; void * thread_ret; init_gpio(); pthread_create( &get_time_thread, NULL, time_to_dispbuf, NULL); pthread_create( &get_temp_thread, NULL, temp_to_dispbuf, NULL); while (1) { int i; for(i=0;i<DISPBUF_LEN;i++){ digitalWrite(latchPin, 0); shiftOut(dataPin, clockPin, MSBFIRST, 1<<i); shiftOut(dataPin, clockPin, MSBFIRST, dispbuf[i]); digitalWrite(latchPin, 1); usleep(1000); } } pthread_join(get_time_thread,&thread_ret); pthread_join(get_temp_thread,&thread_ret); return 0; }