Last active
April 9, 2019 20:49
-
-
Save dhildreth/9d61c6989024c16c1d3a15232f85a131 to your computer and use it in GitHub Desktop.
TS-7680 4-20mA Current Loop Example Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This gist provides example code for working with a 4-20mA current loop | |
sensor, specifically temperature, on a TS-7680. It can be applied to | |
other 4-20mA sensors as well. Here are some steps to run before using | |
the code in this gist on a TS-7680: | |
# Setup networking | |
dhclient eth0 | |
# Install packages | |
sed -i 's/httpredir/archive/g' /etc/apt/sources.list | |
apt-get update | |
apt-get install build-essential bc | |
# Compile and install getadc | |
make | |
# Run getadc | |
getadc 0 | |
# Run rtdTemp.sh | |
chmod +x rtdTemp.sh | |
./rtdTemp.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
* getadc.c | |
* | |
* Based on mx28adcctl.c example code from Technologic Systems, getadc.c will | |
* read current loop values (mV and uA) from a given ADC channel and flash the | |
* "Activity" LED. Refer to the TS-7680 manual for more informtation. | |
* | |
* Example usage: ./getadc 0 | |
* | |
* To compile, simply run `sudo make`. The included Makefile will compile, | |
* install to /usr/local/bin/, and setup executable permissions so it can be run | |
* as a normal user without the need for sudo. Run `make clean` to uninstall. | |
* | |
*******************************************************************************/ | |
#include <assert.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <string.h> | |
void gpioExport(int gpio) | |
{ | |
int fd; | |
char buf[255]; | |
fd = open("/sys/class/gpio/export", O_WRONLY|O_SYNC); | |
sprintf(buf, "%d", gpio); | |
write(fd, buf, strlen(buf)); | |
close(fd); | |
} | |
void gpioDirection(int gpio, int direction) // 1 for output, 0 for input | |
{ | |
int fd; | |
char buf[255]; | |
sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio); | |
fd = open(buf, O_WRONLY|O_SYNC); | |
if (direction) | |
{ | |
if( write(fd, "out", 3) != 3 ) { | |
perror("write failed"); | |
} | |
} | |
else | |
{ | |
if( write(fd, "in", 2) != 2 ) { | |
perror("write failed"); | |
} | |
} | |
close(fd); | |
} | |
void gpioSet(int gpio, int value) | |
{ | |
int fd; | |
char buf[255]; | |
sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio); | |
fd = open(buf, O_WRONLY|O_SYNC); | |
sprintf(buf, "%d", value); | |
if( write(fd, buf, 1) != 1 ) { | |
perror("write failed"); | |
} | |
close(fd); | |
} | |
int main(int argc, char **argv) { | |
volatile unsigned int *mxlradcregs; | |
volatile unsigned int *mxhsadcregs; | |
volatile unsigned int *mxclkctrlregs; | |
unsigned int i, x; | |
unsigned long long chan[8] = {0,0,0,0,0,0,0,0}; | |
int devmem; | |
int activityLed = 58; | |
int adcPair1 = 231; | |
int adcPair2 = 232; | |
// Setup Activity LED | |
gpioExport(activityLed); | |
gpioDirection(activityLed, 1); | |
// Setup all ADCs for 4-20mA Current Loop | |
gpioExport(adcPair1); | |
gpioDirection(adcPair1, 1); | |
gpioSet(adcPair1, 1); | |
gpioExport(adcPair2); | |
gpioDirection(adcPair2, 1); | |
gpioSet(adcPair2, 1); | |
// EN_CL_0_1 is an FPGA IO, which is somewhat slow. | |
// Give it time to catch up. | |
usleep(5000); | |
// Turn on the activity LED | |
gpioSet(activityLed, 0); // 1 = off, 0 = on | |
devmem = open("/dev/mem", O_RDWR|O_SYNC); | |
assert(devmem != -1); | |
// LRADC | |
mxlradcregs = (unsigned int *) mmap(0, getpagesize(), | |
PROT_READ | PROT_WRITE, MAP_SHARED, devmem, 0x80050000); | |
mxlradcregs[0x148/4] = 0xfffffff; //Clear LRADC6:0 assignments | |
mxlradcregs[0x144/4] = 0x6543210; //Set LRDAC6:0 to channel 6:0 | |
mxlradcregs[0x28/4] = 0xff000000; //Set 1.8v range | |
for(x = 0; x < 7; x++) | |
mxlradcregs[(0x50+(x * 0x10))/4] = 0x0; //Clear LRADCx reg | |
for(x = 0; x < 10; x++) { | |
mxlradcregs[0x18/4] = 0x7f; //Clear interrupt ready | |
mxlradcregs[0x4/4] = 0x7f; //Schedule conversaion of chan 6:0 | |
while(!((mxlradcregs[0x10/4] & 0x7f) == 0x7f)); //Wait | |
for(i = 0; i < 7; i++) | |
chan[i] += (mxlradcregs[(0x50+(i * 0x10))/4] & 0xffff); | |
} | |
mxhsadcregs = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, | |
devmem, 0x80002000); | |
mxclkctrlregs = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, | |
devmem, 0x80040000); | |
// HDADC | |
//Lets see if we need to bring the HSADC out of reset | |
if(mxhsadcregs[0x0/4] & 0xC0000000) { | |
mxclkctrlregs[0x154/4] = 0x70000000; | |
mxclkctrlregs[0x1c8/4] = 0x8000; | |
//ENGR116296 errata workaround | |
mxhsadcregs[0x8/4] = 0x80000000; | |
mxhsadcregs[0x0/4] = ((mxhsadcregs[0x0/4] | 0x80000000) & (~0x40000000)); | |
mxhsadcregs[0x4/4] = 0x40000000; | |
mxhsadcregs[0x8/4] = 0x40000000; | |
mxhsadcregs[0x4/4] = 0x40000000; | |
usleep(10); | |
mxhsadcregs[0x8/4] = 0xc0000000; | |
} | |
mxhsadcregs[0x28/4] = 0x2000; //Clear powerdown | |
mxhsadcregs[0x24/4] = 0x31; //Set precharge and SH bypass | |
mxhsadcregs[0x30/4] = 0xa; //Set sample num | |
mxhsadcregs[0x40/4] = 0x1; //Set seq num | |
mxhsadcregs[0x4/4] = 0x40000; //12bit mode | |
while(!(mxhsadcregs[0x10/4] & 0x20)) { | |
mxhsadcregs[0x50/4]; //Empty FIFO | |
} | |
mxhsadcregs[0x50/4]; //An extra read is necessary | |
mxhsadcregs[0x14/4] = 0xfc000000; //Clr interrupts | |
mxhsadcregs[0x4/4] = 0x1; //Set HS_RUN | |
usleep(10); | |
mxhsadcregs[0x4/4] = 0x08000000; //Start conversion | |
while(!(mxhsadcregs[0x10/4] & 0x1)) ; //Wait for interrupt | |
for(i = 0; i < 5; i++) { | |
x = mxhsadcregs[0x50/4]; | |
chan[7] += ((x & 0xfff) + ((x >> 16) & 0xfff)); | |
} | |
if (argc < 2) { | |
printf("%s returns the analog input voltage in mV\n", argv[0]); | |
printf(" Usage: %s <ADC_PIN_NUMBER>\n", argv[0]); | |
// Turn off activity LED | |
gpioSet(activityLed, 1); | |
// Set ADCs back to normal | |
gpioSet(adcPair1, 0); | |
gpioSet(adcPair2, 0); | |
return 1; | |
} | |
int adcPin = atoi(argv[1]); | |
unsigned int meas_mV, uA; | |
meas_mV = ((((chan[adcPin]/10)*45177)*6235)/100000000); | |
uA = (((meas_mV)*1000)/240); | |
printf("mV: %d\n", meas_mV); | |
printf("uA: %d\n", uA); | |
// Turn off activity LED | |
gpioSet(activityLed, 1); | |
// Set ADCs back to normal | |
gpioSet(adcPair1, 0); | |
gpioSet(adcPair2, 0); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NAME=getadc | |
SRCS=getadc.c | |
CFLAGS=-fno-tree-cselim -Wall -O0 -mcpu=arm9 -o $(NAME) | |
CC=gcc | |
INSTALL=/usr/local/bin/ | |
all: main install | |
main: $(SRCS) | |
$(CC) $(CFLAGS) $(SRCS) | |
chown root:root $(NAME) | |
chmod 4755 $(NAME) | |
install: | |
cp $(NAME) $(INSTALL)$(NAME) | |
clean: | |
/bin/rm -f $(NAME) | |
/bin/rm -f $(INSTALL)$(NAME) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#### | |
# Assumes output from getadc to be: | |
# mV: 2732 | |
# uA: 11383 | |
#### | |
uA=$(getadc 0 | awk 'FNR == 2 {print $2}') | |
mA=$(echo "scale=3; $uA / 1000" | bc) | |
#### | |
# For RTD PT100 4-20mA, -50C to 100C transmittor, | |
# the formula is (where x is temp in C and y is mA): | |
# | |
# y = .107x + 9.333 | |
# | |
# Solving for x: | |
# | |
# x = (y - 9.333) / .107 | |
#### | |
tempC=$(echo "scale=1; ($mA - 9.333) / .107" | bc) | |
tempF=$(echo "scale=1; ($tempC * 9/5) + 32" | bc) | |
echo "Temp (C): $tempC" | |
echo "Temp (F): $tempF" | |
#Output: | |
#Temp (C): 19.4 | |
#Temp (F): 66.9 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment