-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathads1115.comp
496 lines (427 loc) · 18.5 KB
/
ads1115.comp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
// This is a component for EMC2 HAL
// Copyright 2015 Martin Kaplan <[email protected]>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
component ads1115 "I2C Interface for ADC ADS1115 (ADS1113 and ADS1114)";
description """
This component is designed as an interface between ADC analog-digital-converter ADS1115 16bit and LINUXCNC through I2C protocol
.SH SYNOPSIS
(ignore the auto-generated SYNOPSIS above)
.SH
.HP
.B loadrt ads1115 cfg=ssd,dd\\fB
Means load two component ads1115. First with two single-ended inputs on pins A0 A1 and one differential input on pins A2 A3.
Second with two differetial inputs on A0 A1 and A2 A3.
Each instance of the component is defined by a group of letters describing the
type of analog inputs. A comma separates individual instances of the component.
.SH Tags
Input type definitions are all lower-case.
s=single-ended (used one pin on ads1115)
d=differencial (used two pins on ads1115)
ADS1115 has 4 input pins A0-A3
The ADS1115 operate from a single power supply VOLTAGE REFERENCE ranging from 2.0V to 5.5V.
An onboard PGA is available on the ADS1114 and ADS1115 that offers input ranges from the supply to as low as ±256mV, allowing both large and small signals to be measured with high resolution.
The ADS1115 communicate with the master (LINUXCNC) through an I2C interface. The master provides a clock signal on the SCL pin and data are transferred via the SDA pin.
.B QUICKSTART GUIDE
Modul automacally generated appropriated pins and parameters for ADS based on cfg sequence.
Communication with ads1115 repeats in cycles:A
Select input (A0-A3)
Send i2c address folowed by write bit to ADC
Send Pointer register for write to Config register (BIT1=0 BIT0=1)
Send MSB Byte (default value are generated by cfg string)
Send LSB Byte
Send address folowed by write bit to ADC
Send Pointer register for read Conversion register (BIT1=0 BIT0=0)
Send i2c address followed by read bit
Read MSB
Read LSB
Go to start with next input
For example to set up gain amplifier to 4.096V (default value = 2.048V) on single-ended input on A0 change A0msb parameter from default value 0xc5 to 0xc3.
0xc5 1100 0101 bit[15]=1 bits[14:12]=100 bits[11:9]=010 bit[8]=1
0xc3 1100 0011 bit[15]=1 bits[14:12]=100 bits[11:9]=001 bit[8]=1
See Config Register
.B REGISTERS
The ADS1115 have four registers that are accessible via the I2C port. The Conversion register contains the result of the last conversion. The Config register allows the user to change the ADS1115 operating modes and query the status of the devices. Two registers, Lo_thresh and Hi_thresh, set the threshold values used for the comparator function.
.B POINTER REGISTER
The four registers are accessed by writing to the Pointer register byte.
BIT 1 BIT 0 REGISTER
0 0 Conversion register
0 1 Config register
1 0 LO_Treshold register
1 1 HI_Treshold register
.B CONVERSION REGISTER
The 16-bit register contains the result of the last conversion in binary twos complement format.
.B CONFIG REGISTER
The 16-bit register can be used to control the ADS1115 operating mode, input selection, data rate, PGA settings, and comparator modes.
Pointer Register Byte (Write-Only)
BIT_7 BIT_6 BIT_5 BIT_4 BIT_3 BIT_2 BIT_1 BIT_0
0 0 0 0 0 0 Reg address
Conversion Register (Read-Only)
BIT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
NAME D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
Config Register (Read/Write)
MSB
BIT 15 14 13 12 11 10 9 8
NAME OS MUX2 MUX1 MUX0 PGA2 PGA1 PGA0 MODE
LSB
BIT 7 6 5 4 3 2 1 0
NAME DR2 DR1 DR0 COMP_MODE COMP_POL COMP_LAT COMP_QUE1 COMP_QUE0
.B Bit[15] OS: Operation Status
For a write status:
0 : No effect
1 : Begin a single conversion (when in power-down mode)
For a read status:
0 : Device is currently performing a conversion
1 : Device is not currently performing a conversion
.B Bits [14:12] MUX[2:0]: Input multiplexer configuration
These bits configure the input multiplexer.
000 : AINP = AIN0 and AINN = AIN1 100 : AINP = AIN0 and AINN = GND
001 : AINP = AIN0 and AINN = AIN3 101 : AINP = AIN1 and AINN = GND
010 : AINP = AIN1 and AINN = AIN3 110 : AINP = AIN2 and AINN = GND
011 : AINP = AIN2 and AINN = AIN3 111 : AINP = AIN3 and AINN = GND
.B Bits [11:9] PGA[2:0]: Programmable gain amplifier configuration
These bits configure the programmable gain amplifier. They serve no function on the ADS1113.
000 : FS = ±6.144V(1) 100 : FS = ±0.512V
001 : FS = ±4.096V(1) 101 : FS = ±0.256V
010 : FS = ±2.048V (default) 110 : FS = ±0.256V
011 : FS = ±1.024V 111 : FS = ±0.256V
.B Bit [8] MODE: Device operating mode
This bit controls the current operational mode
0 : Continuous conversion mode
1 : Power-down single-shot mode (default)
.B Bits [7:5] DR[2:0]: Data rate
These bits control the data rate setting.
000 : 8SPS 100 : 128SPS (default)
001 : 16SPS 101 : 250SPS
010 : 32SPS 110 : 475SPS
011 : 64SPS 111 : 860SPS
.B Bit [4] COMP_MODE: Comparator mode
This bit controls the comparator mode of operation. It changes whether the comparator is implemented as a
traditional comparator (COMP_MODE = '0') or as a window comparator (COMP_MODE = '1').
0 : Traditional comparator with hysteresis (default)
1 : Window comparator
.B Bit [3] COMP_POL: Comparator polarity
This bit controls the polarity of the ALERT/RDY pin. When COMP_POL = '0' the comparator output is active
low. When COMP_POL='1' the ALERT/RDY pin is active high.
0 : Active low (default)
1 : Active high
.B Bit [2] COMP_LAT: Latching comparator
This bit controls whether the ALERT/RDY pin latches once asserted or clears once conversions are within the
margin of the upper and lower threshold values. When COMP_LAT = '0', the ALERT/RDY pin does not latch
when asserted. When COMP_LAT = '1', the asserted ALERT/RDY pin remains latched until conversion data
are read by the master or an appropriate SMBus alert response is sent by the master, the device responds with
its address, and it is the lowest address currently asserting the ALERT/RDY bus line.
0 : Non-latching comparator (default)
1 : Latching comparator
.B Bits [1:0] COMP_QUE: Comparator queue and disable
These bits perform two functions. When set to '11', they disable the comparator function and put the
ALERT/RDY pin into a high state. When set to any other value, they control the number of successive
conversions exceeding the upper or lower thresholds required before asserting the ALERT/RDY pin.
00 : Assert after one conversion
01 : Assert after two conversions
10 : Assert after four conversions
11 : Disable comparator (default)
.B Lo_thresh AND Hi_thresh REGISTERS
Set up tresholds registers are not inplemented on this modul.
""";
pin in bit SDAIn "SDA Input pin";
pin out bit SDAOut "SDA Output pin";
pin out bit SCLOut "SCL Output pin";
pin in bit enable=1 "Turn communication on or offi (default=on)";
pin out bit communication"Communication is ok. True when ADC send Acknowledge bits";
pin out float outA0 if (personality & 0x01)"Analog value between A0 single-ended and GND pins";
pin out float outA1 if (personality & 0x02)"Analog value between A1 single-ended and GND pins";
pin out float outA0-A1 if (personality & 0x04)"Analog value between A0 and A1 pins";
pin out float outA2 if (personality & 0x08)"Analog value between A2 single-ended and GND pins";
pin out float outA3 if (personality & 0x10)"Analog value between A3 single-ended and GND pins";
pin out float outA2-A3 if (personality & 0x20)"Analog value between A2 and A3 pins";
param rw unsigned A0msb=0xc5 if (personality & 0x01) "MSB byte for A0";
param rw unsigned A0lsb=0x83 if (personality & 0x01) "LSB byte for A0";
param rw unsigned A1msb=0xd5 if (personality & 0x02) "MSB byte for A1";
param rw unsigned A1lsb=0x83 if (personality & 0x02) "LSB byte for A1";
param rw unsigned A0-A1msb=0x85 if (personality & 0x04)"MSB byte for A0-A1";
param rw unsigned A0-A1lsb=0x83 if (personality & 0x04)"LSB byte for A0-A1";
param rw unsigned A2msb=0xe5 if (personality & 0x08) "MSB byte for A2";
param rw unsigned A2lsb=0x83 if (personality & 0x08) "LSB byte for A2";
param rw unsigned A3msb=0xf5 if (personality & 0x10) "MSB byte for A3";
param rw unsigned A3lsb=0x83 if (personality & 0x10) "LSB byte for A3";
param rw unsigned A2-A3msb=0xb5 if (personality & 0x20)"MSB byte for A2-A3";
param rw unsigned A2-A3lsb=0x83 if (personality & 0x20)"LSB byte for A2-A3";
param rw unsigned address = 0x48 "address selector-ADDR PIN 0x48=GROUND,0x49=VDD";
function make_puls nofp "Fast thread for generating puls";
function read fp "Slow thread for read value from ADC";
option extra_setup yes;
option count_function yes;
option personality;
license "GPL";
author "Martin Kaplan";
variable int ACKcount=0;
variable int ByteStatus = 0;
variable int BitStatus = 0;
variable int ByteNum = 8;
variable int TXByte;
variable int TXBit;
variable int RXByte;
variable int RXBit;
variable int RxWord [10];
variable int wordnum =0;
variable int lastwordnum;
variable int sentense=0;
variable int lastsentense;
variable int CmdByte = 0;
variable int RxByteNum = 0;
variable int wait;
variable double timer;
;;
enum I2C_mask
{
StartBit = 0x0100, //Generate SDA High>Low on SCL is High
AckBit = 0x0200, //Send low on SDA if Dir=Read
StopBit = 0x0400, //Genarate SDA Low>High on SCL is High
DirBit = 0x0800, // Direction 0=write 1=read
WaitBit = 0x1000, //Wait for ms on 0xffff position
AddressBit = 0x2000, //Write address to byte
ParamMSBBit = 0x4000, //mask byte by parameter MSB
ParamLSBBit = 0x8000 //mask byte by parameter LSB
};
enum I2C_Byte_status
{
ByteIdle = 0, //Idle
ByteNew = 1, //New byte
ByteStart = 2, //Start byte
Byte7_1 = 3, //Bytes 1-7
Byte0 = 4, //Last Byte
ByteAck = 5, //ACK
ByteStop = 6 //Stop byte
};
enum I2C_Bit_Status
{
BitIdle = 0, //Bit is IDLE
BitNew = 1, //Send TXbit to SDA
BitData = 2, //Send High to SCL
BitLow = 3, //SCL is Low
BitHigh = 4, //SCL is Hig
BitStart = 5, //Send SDA High->Low while SCL is High
BitStop = 6 //Send SDA Lowi->High while SCL is High
};
#define MAX_CHAN 4
#define MAX_TXWORDS 10
const int TXWord[MAX_TXWORDS] = {0x2100, 0x01, 0x4000, 0x8400, 0x1002, 0x2100, 0x400, 0x2101, 0xa00, 0xe00};
static char *cfg[MAX_CHAN];
RTAPI_MP_ARRAY_STRING(cfg, MAX_CHAN, "Description of each channel");
FUNCTION(make_puls)
{
if (enable) {
// Cycles through Bytes
if (BitStatus == BitIdle){
switch (ByteStatus) {
case ByteNew :
if ((TXByte & StartBit) == StartBit){
ByteStatus=ByteStart;
TXBit = 1;
BitStatus = BitNew;
} else {
ByteStatus=Byte7_1;
}
break;
case ByteStart :
ByteStatus = Byte7_1;
break;
case Byte7_1 :
ByteNum--;
TXBit = ((TXByte & DirBit)==0) ? (TXByte >> ByteNum) & 0x01 : 1;
RXByte = (RXByte << 1) | RXBit;
if (ByteNum == 0){
ByteNum=8;
ByteStatus=Byte0;
}
BitStatus = BitNew;
break;
case Byte0 :
TXBit=((TXByte & DirBit)==0) ? 1 : ((TXByte>>9) & 0x01) ^0x01; //ACK
RXByte = (RXByte << 1) | RXBit;
BitStatus = BitNew;
ByteStatus = ByteAck;
break;
case ByteAck :
RXByte = (RXBit==0) ? RXByte|0x0200 : RXByte;
if ((TXByte & StopBit) == StopBit){
ByteStatus=ByteStop;
} else {
ByteStatus=ByteIdle;
}
break;
case ByteStop :
TXBit = 0;
BitStatus =BitNew;
break;
default :
ByteStatus=ByteIdle;
}
}
// Cycles through bits
switch (BitStatus) {
case BitNew :
BitStatus = BitData;
SDAOut = TXBit;
break;
case BitData :
BitStatus = BitHigh;
SCLOut = 1;
break;
case BitHigh :
RXBit = (SDAIn && ByteStatus!=ByteStart) ? 1 : 0;
if (ByteStatus==ByteStart) {
BitStatus = BitStart;
SDAOut = 0;
} else {
if (ByteStatus==ByteStop) {
BitStatus = BitStop;
SDAOut = 1;
} else {
BitStatus = BitLow;
SCLOut = 0;
}
}
break;
case BitLow :
BitStatus = BitIdle;
break;
case BitStart :
BitStatus = BitLow;
SCLOut = 0;
break;
case BitStop :
BitStatus = BitIdle;
SCLOut = 1;
ByteStatus=ByteIdle;
break;
case BitIdle :
break;
default :
BitStatus = BitIdle;
SCLOut = 1;
SDAOut = 1;
}
}
}
FUNCTION(read)
{
if (ByteStatus == 0 && BitStatus == 0){
RxWord[lastwordnum]=RXByte;
if (((TXByte & DirBit) == 0x00) && (( TXByte & WaitBit) != WaitBit)) { //write and non wait
if ((RXByte & AckBit) == AckBit) { //ACK returned by client- communication is ok
ACKcount++;
} else {
ACKcount=0;
}
}
if (ACKcount>=5){
communication=1;
}else {
communication=0;
}
TXByte = TXWord[wordnum];
lastwordnum=wordnum;
if ((TXByte & WaitBit) == WaitBit) {
timer += period;
wait=(TXByte & 0xfff)*1000*1000; //ns to ms
if(timer >= wait) {
timer = 0.0;
wordnum++;
}
if (wordnum==MAX_TXWORDS){
wordnum=0;
}
} else {
wordnum++;
TXByte=((TXByte & AddressBit)==AddressBit) ? TXByte|(address<<1) : TXByte ; //mask by address moved 1 bit left
switch (lastsentense){
case 0:
TXByte=((TXByte & ParamMSBBit)==ParamMSBBit) ? TXByte|A0msb : TXByte ;
TXByte=((TXByte & ParamLSBBit)==ParamLSBBit) ? TXByte|A0lsb : TXByte ;
break;
case 1:
TXByte=((TXByte & ParamMSBBit)==ParamMSBBit) ? TXByte|A1msb : TXByte ;
TXByte=((TXByte & ParamLSBBit)==ParamLSBBit) ? TXByte|A1lsb : TXByte ;
break;
case 2:
TXByte=((TXByte & ParamMSBBit)==ParamMSBBit) ? TXByte|A0_A1msb : TXByte ;
TXByte=((TXByte & ParamLSBBit)==ParamLSBBit) ? TXByte|A0_A1lsb : TXByte ;
break;
case 3:
TXByte=((TXByte & ParamMSBBit)==ParamMSBBit) ? TXByte|A2msb : TXByte ;
TXByte=((TXByte & ParamLSBBit)==ParamLSBBit) ? TXByte|A2lsb : TXByte ;
break;
case 4:
TXByte=((TXByte & ParamMSBBit)==ParamMSBBit) ? TXByte|A3msb : TXByte ;
TXByte=((TXByte & ParamLSBBit)==ParamLSBBit) ? TXByte|A3lsb : TXByte ;
break;
case 5:
TXByte=((TXByte & ParamMSBBit)==ParamMSBBit) ? TXByte|A2_A3msb : TXByte ;
TXByte=((TXByte & ParamLSBBit)==ParamLSBBit) ? TXByte|A2_A3lsb : TXByte ;
break;
}
if (lastwordnum==0){
if((personality & 0x01) && (lastsentense==0)) outA0=((RxWord[8]&0xff)<<8)|(RxWord[9]&0xff);
if((personality & 0x02) && (lastsentense==1)) outA1=((RxWord[8]&0xff)<<8)|(RxWord[9]&0xff);
if((personality & 0x04) && (lastsentense==2)) outA0_A1=((RxWord[8]&0xff)<<8)|(RxWord[9]&0xff);
if((personality & 0x08) && (lastsentense==3)) outA2=((RxWord[8]&0xff)<<8)|(RxWord[9]&0xff);
if((personality & 0x10) && (lastsentense==4)) outA3=((RxWord[8]&0xff)<<8)|(RxWord[9]&0xff);
if((personality & 0x20) && (lastsentense==5)) outA2_A3=((RxWord[8]&0xff)<<8)|(RxWord[9]&0xff);
lastsentense=sentense;
do {
sentense++;
if (sentense>=6) sentense=0;
}while (!((personality>>sentense)&0x01));
}
if (wordnum==MAX_TXWORDS) wordnum=0;
ByteStatus = ByteNew;
RXByte=0;
}
}
}
EXTRA_SETUP(){
int i,nextbit=0;
char c;
for (i = 0; cfg[extra_arg][i] != 0 && i < MAX_CHAN ; i++){
c = cfg[extra_arg][i];
if (c == 's' ) {
if (i==2 && nextbit==0) nextbit=1;
if (i==3 && nextbit!=0) nextbit=1;
personality |= 0x01<<(i+nextbit);
}
if (c == 'd' && (i==1 || i==2)) {
personality |= 0x01<<5;
nextbit=5;
}
if (c == 'd' && i==0) {
personality |= 0x01<<2;
nextbit=2;
}
}
personality&=0x3f; // only firs 6 bits
return 0;
}
int get_count(void){
int i;
for (i=0; cfg[i] != NULL && i < MAX_CHAN; i++){}
if (i == 0){
rtapi_print_msg(RTAPI_MSG_ERR, "The ads1115 component needs at least one "
"feedback type tag.\nValid tags are s and d \nexample: loadrt ads1115 cfg=ssd" );
return 0;
}
return i;
}