RobotC-I2C Interface Packet

RobotC I2C Interface Tutorial
– Packet II
Storming Robots
Computational Thinking and Engineering For Kids
RobotC-I2C Interface Packet
Scope: This tutorial will show steps to interface with I2C sensors.
Before we go into programming to I2C interfaces, there are a few things you should have a fair amount of
knowledge, or at least know what they represent:
Data structure – “struct” and “array” (this should been introduced in the Programming Packet II)
Bits / hexadecimal representation. (in this document)
What is a Memory Address? What is a bus? (in this document)
Table of Contents
1|Page
RobotC I2C Interface Tutorial
– Packet II
2|Page
Storming Robots
Computational Thinking and Engineering For Kids
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH1 – LEARNING ABOUT BITS & BYTES
CH1 – 1 BINARY & HEXADECIMAL BASED
Decimal number is base-10.
e.g.
valid digit: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
number 204910 = 103 * 2 + 102 * 0 + 101 * 4 + 100 * 9
Binary number is base-2.
e.g. valid digit: 0, 1
10102 = 23 * 2 + 22 * 0 + 21 * 1 + 100 * 0
= 1010
100010010
 most
significant bit
least 
significant bit
Hexadecimal number is base-16.
e.g. valid digit: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
1000016 = 164 * 1 + 163 * 0 + 163 * 0 + 163 * 0 + 160 * 0
= 6553610
FFFF16
= 163 * 15 + 162 * 15 + 162 * 15 + 161 * 15 + 160 * 15
= 6553510
3|Page
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH1 – 2
CONVERSION
From Decimal
to Binary
2 ) 18 .
1810
= 100102
2 ) 15 .
1510
2 ) 9
---0
2 ) 7
---1.
2 ) 4
---1
2 ) 3
---1.
2 ) 2
---0.
1
---1.
1
=
11112
---0
From Decimal
to Hexadecimal
16) 18 .
From Binary to
Decimal
100102
111110
= 24 * 1 + 2 1 * 1
= 23 * 1 + 2 2 * 1 + 21 * 1 + 2 0 * 1
= 1510
1
1810
= 1216
---2
0
= 1810
From
Bin
From
Hex
Hex
Bin
to
to
1510
0x0149AF
016 = 010 = 02
016 = 010 = 02
416 = 410 = 01002
416 = 410 = 01002
916 = 910 = 10012
916 = 910 = 10012
A16 = 1010 = 10102
A16 = 1010 = 10102
F16 = 1510 = 11112
F16 = 1510 = 11112
01110010101010112
00011000100010002
7
2
5
11
1
= 163 * 7 +
160 * 11
= 2927510
= 0F16
---F
0x0149AF
= 725B16
4|Page
16) 15 .
8
8
8
= 188816
162 * 2 +
161 * 5 +
= 163 * 1 +
160 * 8
= 628010
162 * 8 +
161 * 8 +
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH1 – 3
SIGNED BIT
1 byte = 8 bits
4 bytes = 1 Word, ie 32 bits
Data type: byte or char
Contains 1 byte
Can only hold 7 bits number representation, instead of 8 bits, because the highest significant bit is reserved
as a signed bit.
Signed byte: signed bit
0/1 0/1 0/1 0/1 0/1 0/1 0/1
7th
6th 5th
4th 3rd 2nd 1st 0th
If “signed bit” == 1, this is a negative
If “signed bit” == 0, this is a positive
e.g.
byte x = 0100 00012 = 0x41 = 65
byte x = 1011 11112 = 0xbF = -65. You may ask why not 1100 00012.
To make 65  -65 :
1. Take ~0100 0001 = 1011 11102
2. + 1 = 1011 11112
Just for fun:
For byte x = 1100 00012 = -63
1. 1100 00012 - 1
2. ~1100 00002 = 0011 11112 = 0x3F = 63
Data type: unsigned byte or char
Contains 1 byte
Can hold 8 bits number representation.
Unsigned byte:
0/1 0/1 0/1 0/1 0/1
th
7
6th
5th
4th
e.g.
unsigned byte x = 10000012 = 65
unsigned byte x = 110000012 = 193
0/1
3rd
0/1
2nd
0/1
1st
0th
Question: int x = 64 (2 bytes integer)
Negative of x = _________________________
(Fill in the blank)
CH1 – 4 BITWISE MATH OPERATION
A bitwise operation operates at the level of individual bits between two binary numbers. This is indispensable
knowledge in electronic as you will see how these are used in sensors data operation in later exercises.
You can do Binary Addition, Subtraction, Multiplication, and Division, like more other basic arithmetic. What we
will focus on here is “bit shifting”, and “bit masking” operations.
Bitwise operation is far faster than multiplication and division in computer.
5|Page
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
Ch1 – 4.1 Bit Masking : OR (inclusive OR)
Operator:
|
Function: set bits on
e.g. x = 0102;
y = 1112,
x = x |
y, i.e. x == 1112
Ch1 – 4.2 Bit Masking : AND
Operator:
&
Function : find out which particular bit(s) is/are set.
e.g. x = 0102;
e.g. x = 1112;
y = 1112,
y = 1012,
x = x & y, i.e. x == 0102
x = x & y, i.e. x == 1012
Ch1 – 4.3 Bit Masking : XOR (exclusive OR)
Operator:
^
Function: set bits off or switch bit on& off
e.g.
e.g.
e.g.
e.g.
x
x
x
x
=
=
=
=
0102; y = 1112, x = x ^ y,
1012; y = 1012, x = x ^ y,
1; y = 1; x = x^y; i.e.
0; y = 1; x = x^y; i.e.
i.e. x == 1012
i.e. x == 02
x==0 // great to be used as an on/off switch
x==1
Ch1 – 4.4 Bit Masking : NOT (complement)
Operator: ~
Function:, is a unary operation that performs logical negation on each bit
e.g. x = 0102; ~x == 1012
e.g. x = 1; ~x == 0 // great to be used to alternate on/off state
e.g. x = 0; ~x == 1
Quickly recapture the bitwise operations:
6|Page
Bit
3
Bit
2
Bit
1
Bit
0
X
1
1
0
0
Y
1
0
1
0
Bit-And
Z=X&Y
1
0
0
0
Bit-OR (inclusive)
Z=X|Y
1
1
1
0
Bit-XOR
(exclusive)
Z=X^Y
0
1
1
0
Bit-NOT
Z = ~X
0
0
1
1
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
Caution! Do not use bit shift unless you FULLY aware of the signed and unsigned relationship, as well as binary
math operation.
If you have to use it, you should write a separate program to test out all signed and signed
situation to ensure you will not have shifting errors.
CH1 – 5 BIT-SHIFT OPERATION
Ch1 – 5.1 Shift left
Operator : <<
Function: multiple by 2n
e.g. x = 1010 * 2 1; i.e. 10102 << 1
then x contains 20 , i.e 101002
e.g. x = 1010 * 2 2; i.e. 10102 << 2
then x contains 40 , i.e 1010002
Ch1 – 5.2 Shift right
Operator : >>
Function: divided by 2n
e.g. x = 1010 / 2 1; i.e. 10102 >> 1
then x contains 5, i.e 1012
e.g. x = 1010 / 2 2; i.e. 10102 >> 2
then x contains 2, i.e 102
(note that not 2.5 because this is supposed to deal with “int” data type, not float)
CH1 – 6
MORE ON BITS MATH FOR PERFORMANCE
In modern computer architecture, multiplication and division have been optimized to the point that it performs
just as good as bits operation. The only one which will still be faster with bit math is calculating X^n, instead of
using power(X, n).
Pseudo code for doing your power X^n:
Calculate Xn
Put bits math above in good use, let’s try to calculate XN, e.g. 93.
Let n1 , n2 = X
for I from 1 to exponent N
{
while n2 != 0
{
If
last bit of n2 != 0
sum = sum + n1
n1 << 1
n2 >> 1
}
Set n1 to sum
Reset n2 = operand
7|Page
9x9=81
*
81x9=729
1010001
1001
1001
0000
0000
1001
1010001
(n2)
1010001
0000000
0000000
.
1011011001
1001
(
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
}
CH1 – 7 EXERCISE:
Ex 1: Complete all the conversions below
A) Conversion: base2(binary) vs. base10(decimal) vs. base16(hexadecimal)
Binar
y
Dec.
1
1
Ox17
11
3
0x1F
Hex.
Binary
Dec.
Hex.
10001
0x88
10010
0x100
10100
0x10F
11000
0x00F
11011
0xF0
B) Calculate the following, and provide answer in hexadecimal format:
i.
1610 & 1510 ? Ans: __________________
ii.
1610 | 1510 ? Ans: __________________
iii.
1C16 | 112 ? Ans: __________________
iv.
1C16 | 110000002. ? Ans: _________________
v.
1610 ^ 1510 ? Ans: __________________
vi.
1616 ^ 1516? Ans: __________________
vii.
byte x = 310;
viii.
ubyte x = 310;
What is ~x?
What is ~x?
Ans: __________________
Ans: __________________
ix.
byte x = 0. Use a single bit masking method to get value of 0xF.
Ans: __________________
x.
byte x = 101. Use a single bit masking method to get value of 0x3.
Ans: _________________
C) Use Bit-math to do the following (the first is done for you):
i.
X = 0x1C. Write the binary representation. Ans:
0001 1100
ii.
Calculate 20 / 4 using binary math.
iii.
X = 0x1C. Get only the least (lowest) significant 2 bits. Ans: __________________
iv.
X = 0x1C.
Ans: __________________
Get only the most (highest) significant 2 bits.
Ans: __________________
D) Write a program to extract data from two separate data fields and reassemble it to form an new data field.
Result = move the least significant 2 bits of field2 into the most significant position of result.
Move the most significant 2bits of field1 into the least significant position of result.
8|Page
RobotC I2C Interface Tutorial
– Packet II
e.g.
If
then
Storming Robots
Computational Thinking and Engineering For Kids
int field1 = 0xdb02
int field2 = 0x1f06
int result should be = 0x1011
Ex2: Write a display function to display an integer and/or char field in binary and hex
value:
o
Specification of this function can be : void displaybits(char x)

Return: none

Parameter : char x : is one byte integer. Your function will display its binary
representation.

E.g. char abc = 254;

displayBits(abc);


Your nxt should display : FE 11111110


E.g. char abc = 16;

displayBits(abc);


Your nxt should display : 10 10000
Hint:
For the hex display, it is easy… just use %x in your display
For binary display, use:
binary shift
Put each bit in a character array and a string, e.g char arr[9]; string str;
Shift the bit : LSB to arr[7] … MSB to arr[0];
Use StringFromChars(str, arr)…well. You need to do this because RobotC cannot do display a character
array. It must be in string format.
9|Page
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH2 – SET AND ACCESS I2C PORTS
CH2 – 1 BASIC TERMS
What is Memory Address ?
Computers only understand binary. Any hardware must have way to store its request and data, ie. the Memory
Address.
Do not confuse this with the term Memory Register, although it is often referenced as such online by
people using I2C code. A register is a bit placeholder for bits information stored in very fast memory/storage
access area. This is built into the CPU (central processing unit) in order to speed up its operations by providing
quick access to commonly used values. For this I2C reference, they use the term Register loosely as it means
the memory address storing either instruction or data. Note: as far as memory is concerned, a memory address
is memory address; it does not matter what you store it.
In short, it represents bits and bytes of request. Registers are the top of the memory hierarchy and are the
fastest way for the system to manipulate request.
Typical uses of hardware registers include configuration and start-up of certain features, especially during
initialization, storage configuration for hardware devices, such as central processing unit, I/O devices like
sensors. etc.
Before you operate on the register request from a device, you need to know the “memory address layout”.
short, it is a request map where you can get important request from the device like the tilt sensor.
e.g.
nDeviceAddress = 0x02;
nLocationPtr = 0x42;
In
// the unique address of a I2C device
// the address referring to a certain command for actiion
What is a Bus ?
A bus, as a computer term, may represent two things.
1. It can mean the physical electrical wires with multiples connections for hardware devices.
2. It can also mean any subsystem that provides a specific set of functionality as an electrical bus.
Internal and external buses:
Internal buses all the internal components of a computer to the motherboard, e.g. CPU, math processor,
internal memory modules, etc. They are also called local bus. There are motherboard specific.
External buses connect external peripherals to the motherboard, such as the USB.
10 | P a g e
RobotC I2C Interface Tutorial
– Packet II
Storming Robots
Computational Thinking and Engineering For Kids
CH2 – 2 INTRODUCTION TO I2C PORTS
I2C means Inter-Integrated Circuit. It generically is referred as "two-wire interface". This is standardized
bus design that has become very popular because
low manufacturing cost
its small size
low weight,
low power consumption.
I2C system design was created in the early 1980s, and standardized in early 1990s. It is have widely used in
implementing peripheral devices. Ever since then, the physical size has been decreasing drastically. The speed
has increased as well, ranging from 10 to 400 kbits/sec :
10kbits/s as low speed mode
100kbits/s classified as standard speed
400kbits/s as high speed mode
11 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH2 – 3 I2C PORTS TEST UTILITY IN ROBOTC
ROBOTC provides a tool for testing digital sensors on the NXT.
Digital sensors are those that support the industry standard I2C protocol for communications between the NXT
and the sensor. The utility allows you to easily test an I2C sensor on the NXT.
To do this, you should find out the I2C address map from the sensor that you are interested in. For simplicity,
we are going to use the NXT ultrasonic sensor as an example. Steps :
This section of information is largely extracted from the RobotC-I2C document.
Invoke the I2C ports test utility
Manual test out the responses from I2C Test Utility
The following window shows up. When this utility is first opened, it will interrogate the NXT to get the current
settings of these values.
Sample steps:
-
Hook up an ultrasonic sensor which is an I2C custom sensor as well.
Run the utility.
Type the entries shown below:
Port
I2C sensors port
The hexadecimal bytes of the message to be sent to
the sensor
Output Message
Reply Len (Length)
12 | P a g e
RobotC I2C Interface Tutorial
– Packet II
The length of the reply expected from the sensor in
bytes
Reply
The reply returned from the sensor in hexadecimal
(and converted to ASCII)
Select
A checkbox to determine if the selected message
should be included or excluded from the test cycle.
Once/Continuous Buttons
These buttons select whether a single test cycle or
continuous testing should be performed.
Verify Write
If checked, the NXT will send an ACK message to
check if the I2C message was successfully sent to
the NXT. The "Failed" text box will return a count of
the number of failed messages.
Storming Robots
Computational Thinking and Engineering For Kids
Count
A text box containing the number of messages sent
in total.
Bus Errors
Number of bus errors encountered during error
transmission. Bus error is detected by the I2C
firmware and usually indicates an attempt to send
an I2C message to a sensor that does not support
I2C messaging.
No Reply
Number of messages sent to the I2C message that
did not recieve a reply from the sensor.
Diff Msg (Different Message)
Number of different messages recieved from the I2C
sensor... this counter will not increment when the
same message is recieved from the I2C sensor in
succession
Exercise:
Download the utility file called ic2Scanner from http://robotc.stormingrobots.com to detect i2c
devices address.
I2C Fast Sensor vs. I2C Slow Sensors
Use either of these two buttons to quickly configure all four sensor ports as a custom I2C sensor. “Fast” sensors
will use the ROBOTC firmware capability to transmit I2C messages at five times the speed found in the standard
LEGO supplied firmware. Fast mode generally works with all third party sensors, slow mode is required for the
LEGO ultrasonic sensor. The difference is that most 3rd party sensors include a microprocessor that has I2C
messaging support in hardware and can keep up with the faster ROBOTC messaging rate. Slow sensors have a
“bit-banged’ implementation and cannot keep up.
Firmware Version
Configure these parameters for either standard LEGO firmware or ROBOTC firmware. Standard firmware does
not support fast mode signaling and will always try to send a I2C message three times before reporting failures.
Trying three times can easily mask intermittent transient errors. The number of total tries can be user
configured in the ROBOTC firmware. The default value is a total of three tries. Setting the number of retries to
zero is useful to ensure transient errors are not masked.
2|Page
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH2 – 4 WHAT IS I2C ADDRESS, MEMORY ADDRESS & BUS
Memory Address Map
Computers only understand binary. Any hardware must have way to store its data, i.e. memory address.
Memory Address (sometimes they may refer to as register) is a bit placeholder for bits information stored in
very fast memory/storage access area. This is built into the CPU (central processing unit) in order to speed up
its operations by providing quick access to commonly used values.
In short, it represents bits and bytes of data. True Registers are the top of the memory hierarchy and are the
fastest way for the system to manipulate data.
Typical uses of hardware registers include configuration and start-up of certain features, especially during
initialization, storage configuration for hardware devices, such as central processing unit, I/O devices like
sensors. etc.
Before you operate on the register data from a device, you need to know the “register layout”.
data map where you can get important data from the device like the tilt sensor.
In short, it is a
e.g.
nDeviceAddress = 0x02;
nLocationPtr = 0x42;
IMPORTANT: This I2C memory address MUST be even … You will see why when you work with the I2C
code on the Arduino side.
I2C Address vs other Memory Address Commands
In essence, I2C address is memory address.
Distinction should be mentioned:
I2C address : an unique memory address to identify a specific I2C device. In the case when you connect to
multiple I2C devices, you must have an unique memory address to address each single device.
Other Memory addresses are used for certain commands determined by the manufacturer. If you are the one who
create the I2C device, you will be the one who create the I2C unique address, and all other command addresses.
Bus
A bus, as a computer term, may represent two things.
It can mean the physical electrical wires with multiples connections for hardware devices.
It can also mean any subsystem that provides the a specific set of functionality as an electrical bus.
The arrangement may use both parallel (multidrop) and bit-serial (daisy chain) connections.
a USB hub.
One example is
In essence, a design of bus forms a standard interconnection points for which multiple manufacturers build
compatible and interchangeable interfaces.
Internal and external buses:
Internal buses all the internal components of a computer to the motherboard, e.g. CPU, math processor,
internal memory modules, etc. They are also called local bus. There are motherboard specific.
12 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
External buses connect external peripherals to the motherboard, such as the USB.
NXT Sample Memory map model
HiTechnic I2C Sensor memory model:
Address
00-07H
08-0FH
10-17H
18-3DH
3E, 3FH
40H
41H
42H
13 | P a g e
Type
Contents
byte
Reserved
byte
Manufacturer
byte
Sensor type
byte
Not used
byte
Reserved
byte
Not used
Byte
Reserved
Memory Address 42H and higher
will contain layout specific
for different device.
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH2 – 5 BASIC PROGRAMMING OPERATIONS ON I2C DEVICES
Steps to do for interfacing with an I2C sensor:
1) Create a sample data structure to represent the standardized protocol for I2C communication. This sample
shows 3 bytes message size.
Byte msg[3];
// whatever # of bytes that
you will need for your message
size.
typedef struct{
byte nMsgSize;
byte nDeviceAddress;
byte nLocationPtr;
} TI2C_Output;
TI2C_Output sOutput;
OR
2) Initialize I2C sensor port and check the port for communication readiness
SensorType[S1] = sensorI2CCustom;
3) Check the communication status
while (nI2CStatus[S1] == STAT_COMM_PENDING)
wait1Msec(2);
4) Setup device’s internal location, memory address, a “read” command.
sOutput.nMsgSize = 2;
sOutput.nDeviceAddress = 0x02;
sOutput.nLocationPtr = 0x42;
// 0x42 is the address used for a
certain i2c command
sendI2CMsg(S1, &sOutput, 0);
Byte msg[3];
sendI2CMsg(S1, msg, 0);
or
5) Check the communication status
while (nI2CStatus[S1] == STAT_COMM_PENDING)
wait1Msec(2);
6) Read the message:
// prepare the message space.
// N is the # of bytes. Refer to the I2C sensor specification
byte replyMessage[N];
// get the message
readI2CReply(S1, replyMessage, N);
7) Normalize the read value from the Memory Address:
“replyMessage[…]” only returns the raw value.
You may have to do some work to get the normalized (or cooked) value.
This is specific to individual I2C device manufacturer. You must obtain the memory map model from the
I2C sensors manufacturer.
This section shows the basic steps to interface with any I2C devices with NXT. In the later chapters, samples are
given to interface with specific I2C devices.
14 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
More Effective ways to communicate with an I2C sensor
Send a command over to I2C device, but not expecting any value back, such as telling the I2C sensor to do
some configuration, or turning on internal LED, etc.
Msg[0] = 3;
//there are 3 bytes in the message stream
Msg[1] = 0x02;
Msg[2] = 0x42;
Msg[3] = 5;
sendI2CMsg(port, Msg, 4);
//where the value 5
// e.g. it may mean to
//
something more
// The third parameter
may mean some configuration value to the sensor.
tell the sensor turning on its LED, or blink its LED 5 times, or
useful - telling it to do data filtering with 5 data points.
tells the I2C sensor that it expects it to return a 4 bytes value.
Then, your code should do this in order to get 4 bytes back from the I2C sensor :
readI2CReply(S1, replyMessage, 4);
Caution !!!
These APIs preform the bare minimum in a communication mechanism. However, it is far from robust. You
must perform your own error checking, retries, etc., to ensure integrity of a message route. Additional lib rary
layer which comes with RobotC to perform many more detailed tasks to help making your code more robust.
In common.h, you will find two functions in lieu of these two functions. They are writeI2C(…) and
readI2C(…). They did a lot of error checking for you.
With pre-version 3.5, pointers were not supported by RobotC. Depending which version you have with
RobotC, you may need to modify the writeI2C like the following:
bool writeI2C2(tSensors link, char *request, char *reply) ;
bool writeI2C2(tSensors link, char *request, char *reply, int replylen) ;
Before you decide to definitely write a robust I2C communication layer, you should always use
“writeI2C(…)” API instead of the native sendI2Cmsg(…) ,etc.
15 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH2 – 6 INTERFACE WITH NON-NXT I2C DEVICES
2 Big Gotcha-you points to watch out for:
Proprietary libraries
Pull-up resistors
NXT can interface with I2C devices which are not sensors. You should review the devices’ specification, and best
to at least get a logic analyzer to observe the device’s signaling behavior. More examples will be included here:
But in general, you are pretty much on your own!
<…Under construction …>
16 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH2 – 7 I2C COMMUNICATION BETWEEN NXT & ARDUINO FLOW DIAGRAM
Note: Create a shared header file which contains the I2C address for the slave device, as well as all the
command addresses.
I2C Communication Flow Diagram
*** WITH THE ROBOT C NATIVE I2C CALLS
NXT (I2C Master Device)
Arduino (I2C Slave Device)
#include <Wire.h>
volatile uint8_t request=0l
volatile uint8_t value =0; // etc… anything you write
back to the NXT
….
void setup( )
{
…// do not forget the address is the 7 MSB from the
one used in NXT
Wire.begin( I2C device address );
Wire.onReceive( receiveEventFunction );
Wire.onRequest( requestEventFunction );
…
}
Form your I2C message array
sendI2CMsg(port,*msg,0)
void receiveEventFunction (int nbytes)
{ ….
request = Wire.read();
Get the data from the transmission, if any
more available.
OR
Form your I2C message array
sendI2CMsg(port,*msg,
>0)
replyI2CMsg(port, *msg,
#of bytes back)
void receiveEventFunction (int nbytes)
{ ….
}
void requestEventFunction (…)
{…
switch (request)
{ case ….
Wire.write( msg, #of bytes);
17 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
*** WITH THE ROBOT C - XANDER’S I2C
18 | P a g e
CALLS
RobotC I2C Interface Tutorial
– Packet II
Storming Robots
Computational Thinking and Engineering For Kids
CH2 – 7 EXERCISES
Ex1: Learn from the I2C Sample from robotC
Copy the “common.h” from the <your robotC installation directory>\Sample
Programs\NXT\3rd Party Sensor Drivers\drivers. (per up to RobotC version 3.6.x)
Look at various I2C sensors sample codes, such as:
-
Accelerometer
Compass
Sharp IR distance sensor
Light Array
And many more.
Ex2: Write a program to display the distance from the ultrasonic sensor. However, you
are supposed to obtain the distance data via I2C calls and treat it like a custom sensor,
not the one from the default NXT firmware. To do this, you need to do the following:
a)
b)
You may verify it with the RobotC I2C utility to check out the command address like this:
Type : I2C Custom 9V
Output Message: 0x02 0x42
In your code :
SensorType[S1] = sensorCustom9V; // do not set it to sensorSONAR
Ex2: Your task is to write your layer of own communication APIs.
This layer is about robust networking interface practice with I2C protocol, so it is outside the scope of this
document.
However, you are encouraged to look into common.h to examine the proper error checking
steps from Xander’s writeI2C(…) to write more robust networking communication interface.
19 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH3 – HITECHNIC ACCELEROMETER INTERFACE
Accelerometer is used to measure acceleration. It is used to measure a variety of things that are used in large
array of electronic equipment, and robots including Acceleration, Tilt angle, Vibration, or even Gravity.
Big thanks to MEMS, Micro-Electro-Mechanical-Systems under the category of NanoTechnology. It allows a
single accelerometer along with other transmitters all into a single substrate. While we are entering the
NanoTechnology era, accelerometers will permeate our lives as never before!
Applications:
Wii Game Controller, Car airbag deployment, any system which involves human motion monitoring and many
more.
Some educational videos:
o
o
o
The Photolithography process used in M.E.M.S.
Basic MEMS fabrication
Accelerometer measures RC car crash drop from 45ft. - Another Geek Moment
CH3 – 1: FOR ACCELERATION MEASUREMENT:
The NXT Acceleration Sensor contains a three axis accelerometer that measures acceleration in three axes, x, y
and z. Acceleration is measured in the range of –2g to +2g with scaling of approximately
200 counts per g.
The acceleration measurement for each axis is refreshed approximately 100 times per
second. This sensor provides 3-axes data.
To view: You may use the I2C Utility tool if you have RobotC version 2.0+. Otherwise, you can view this using
the ultrasonic selection on the NXT. Only the x-axis value will.
CH3 – 2: FOR TILT MEASUREMENT:
X axis = 0
X axis = 200
X axis = -200
Y axis = 0
Y axis = -200
Y axis = 200
(counterclockwise
)
(clockwise )
(looking at the sensor
from the back)
Z-axis: This becomes not useful as it should show ~200, as it indicates the gravity.
20 | P a g e
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH3 – 3: SENSOR MEMORY ADDRESS LAYOUT
You should write your own view functions to see how your movements are measured in each axis. Viewing the
axis data to determine which axis or axes will best fit your work.
First of all, you need to know the Memory Address layout.
HiTechnic I2C Sensor memory model for the accelerometer (we call it tilt sensor)
Address
42H
43H
44H
45H
46H
47H
Type
byte
byte
byte
byte
byte
byte
Contents
X axis upper
Y axis upper
Z axis upper
X axis lower
Y axis lower
Z axis lower
8
8
8
2
2
2
bits
bits
bits
bits
bits
bits
Sample:
//
//
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
21 | P a g e
i.e.
200 units per 1 g. [where 'g' == acceleration due to gravity]
task main()
{
// Local variables section
int xUpper,xLower;
int yUpper,yLower;
int zUpper,zLower;
int xVal,yVal,zVal;
typedef struct{
byte nMsgSize;
byte nDeviceAddress;
byte nLocationPtr;
} TI2C_Output;
byte replyMessage[6];
long nLoops = 0;
TI2C_Output sOutput;
// done creating local variables
// step 1 : initialize the sensor port
SensorType[S1] = sensorI2CCustomFast;
wait10Msec(5); // give it some time to initialize.
nI2CBytesReady[S1]=0;
// step 2 : wait until the port is ready for operation
while(nI2CStatus[S1]== STAT_COMM_PENDING)
wait1Msec(2);
// step 3 : set up the device's internal location Memory Address index to
//
indicate which of 256 (28) different internal Memory Addresss
//
a "read" command should start at. This is manufacturer specific.
//
Need to look up the HiTechnic’s memory address maplayout
sOutput.nMsgSize = 2;
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
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
69
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
`
22 | P a g e
sOutput.nDeviceAddress = 0x02;
sOutput.nLocationPtr = 0x42;
while(true)
{ ++nLoops;
// simple loop count for testing communication.
nI2CBytesReady[S1] = 0;
// step 4 : Send command to the sensor before read
sendI2CMsg(S1, sOutput, 6);
// send 6 bytes of sOutput
while (nI2CStatus[S1] == STAT_COMM_PENDING)
wait1Msec(2);
memset(replyMessage, 0, 6);
if (nI2CStatus[S1] == NO_ERR)
{
// step 5 : read command to get 6 bytes of data and put them in replyMessage
readI2CReply(S1, replyMessage[0], 6);
// step 6 : normalize the data, i.e. extract and/or parse data
//
from the replyMessage stream
xUpper = replyMessage[0];
yUpper = replyMessage[1];
zUpper = replyMessage[2];
// addr:0x42
// addr:0x43
// addr:0x44
xLower = 0x03 & replyMessage[3];// addr:0x45; only want the lowest 2 bits
yLower = 0x03 & replyMessage[4];// addr:0x46; only want the lowest 2 bits
zLower = 0x03 & replyMessage[5];// addr:0x47; only want the lowest 2 bits
xVal = (xUpper << 2) | xLower;
yVal = (yUpper << 2) | yLower;
zVal = (zUpper << 2) | zLower;
//put xUpper to upper 8 bits + xLower
//
//
nxtDisplayTextLine(4, "x-val %d", xVal);
nxtDisplayTextLine(5, "y-val %d", yVal);
nxtDisplayTextLine(6, "z-val %d", zVal);
}
Else
{ nxtDisplayTextLine(3, "i2c err %d", nI2CStatus[S1]);
}
}
}
Storming Robots
Computational Thinking and Engineering For Kids
RobotC I2C Interface Tutorial
– Packet II
CH4 – OTHER I2C DEVICE INTERFACE
HiTechnic InfraRed Seeker
Need the following 2 files from HiTechnic unless you will write your own I2C interfaces. They are at:


File > Open Sample Programs > 3rd Party Sensor Drivers >drivers
common.c, HTIRS2-driver.h
I2C InfraRed Seeker - version sample
HiTechnic Sensors Mux
HiTechnic has an excellent document about programming interface with Sensors Mux.
More will be added in the future.
23 | P a g e