Sunday, December 19, 2010

A more conscious resource usage

To improve the world we need to change our habits,
reducing pollution and becoming more responsible.

We need to understand.
We need to be more critic, and think more about our environment.

The story of stuff:
a video from Tides Foundation helping us to understand the production cycle of the goods we consume

Our future is in our hands.
We want a better future
We want a better world.


And start doing.

Right time is NOW!


Monday, November 22, 2010

Arduino Wiznet ethernet shield proper reset

 Arduino 2009 Wiznet Ethernet Shield proper reset
 (last modified on nov 22 2010)

Problem: Arduino 2009 with wiznet w5100 ethernet shield does not start network operations after power-up.
It works well if the reset button is pressed.

Solution: I implemented davekw7x's suggestions (THANK YOU!), as cited in this arduino forum page (ref. reply #11)
this solution requires a 10kOhm resistor, and a 10nf capacitor.

Here are the detailed steps and some pictures:

1. bend outwards the ethernet shield reset pin "leg", so that it will not go in the arduino reset socket.
2. solder the 10kOhm resistor between reset pin and the nearby 3.3 Vcc
3. solder the 10nf capacitor between reset pin and ground

Here is a picture of one of my ethernet shields, with the reset "leg" bent outwards.

And this is the details of how I soldered the components on the back of the circuit.
In this position the components are nicely arranged on the back of the board.

With this mod, my arduino + ethernet shield is starting up correctly after powering up, and immediately works with no need of reset button push.

Marco ( @mgua )


Rigol DS1052E Oscilloscope

I finally received the RIGOL DS1052E Scope that I ordered on DealExtreme.

The order from DealExtreme is including shipping.
Unfortunately, a substantial delay (totally unrelated with DealExtreme) was caused by the customs import procedures. Italian posts are terrible.

Overall, it took almost two months to receive the device.
But finally I got it, and in one piece. Package was in good state, and the box was well sealed.

Here is a picture of the product along with box contents, from

I have to say that the product quality is very good, and that usability is good too. (apart from the initial shock of having the default menus in chinese, quickly fixed).

The scope is well built, with good quality sturdy plastic chassis, a good color lcd monitor, and good quality knobs.

Furthermore there is a publicly available hack (check here and to actually double the scope frequency bandwidth to 100MHz, actually turning the Rigol DS1052E into the Rigol DS1102E, which has just a difference in firmware.

Here is the spec comparison of the two models, from the site page describing the hack.

Also this Dave Jones videoblog entry on youtube describes the hack, as well as some tricks in updating the most recent firmwares so to avoid problems.

I did not apply the hack to my scope yet, because I have currently no need of a higher speed. I will do it as soon as I will have the need.

Here are some manuals and documents of this product, taken from Rigol Website:
  User guide
  Programming Guide

Marco (@mgua)


Saturday, October 16, 2010

Farewell mr. Fractal

Benoît Mandelbrot passed away.
He was 85.

He poured colour
On otherwise pale equations

He traced the path
Analyzing the bizarre ways
In which numbers play
Between zero and infinity

He was walking to measure
Britain's coast
At various distances

Fractals call him dad

Now he walks
On the white chalky paths
In the Great Attractor's garden.



Friday, October 15, 2010

Gandalf's grey hat

Gandalf's grey hat

Where did Gandalf put his grey robes,
and his grey hat, after his fight with the Balrog?

Absolutes are easier to deal with than tradeoffs

But real beauty lies in between

In the nuances, in fractal dances

In chaotic indecisions, bouncing on spectre's ends

In misteriously misty shades of grey

In mutations, diversity, evolution

Be alive
Cast Doubt
Ready for change


(crossposted from ebmb)


Monday, October 4, 2010

Hacking Your Car

In this post I will report about my experiences and studies about vehicle electronics.

Last edited on jun 27, 2012

CAVEATS: I found that the generally available informations about this subject on the internet is quite poor and not very clear. While I am trying to do my best in verifying, errors and mistakes could be present.
Please feel free to add your critics and comments.

This is going to be a long term project, so this page will be improved over time.

Cars are complex
Cars are getting complex. Car electronics is really sophisticated, and current cars have dozens of control units for managing devices, sensors, and actions.

ECUs: Elecronic Control Units
The Control Units talk on local vehicle networks, which are similar to a common computer LAN, but based on different protocols.
ECUs, Engine Control Units, were the first to be connected to vehicles network, soon followed by others ECUs (generic Electronic Control Units).
To reduce the amount of signal wires among the many electric components of a modern car, digital communication protocols were introduced, and digital electronic interfaces between every electric device and the communication infrastructure.
The most important ECU is the Engine Control Unit.
Here is a non-exaustive list of Engine Control Unit manufacturers for cars:  BOSCH (example: EDC16),   MAGNETI MARELLI (example: 95160), SAGEM (example: 95080), SIEMENS (example: TMS374).

Here is a PDF file from the chinese company UIF Technology (a supplier of car electronics and diagnostic devices) with pictures of many Engine Control Units.

STANDARDS: a terrible headache
There are many standards defining protocols, signals, diagnostics.
Here is a probably incomplete and maybe wrong list
SAE and ISO are the most common standard and documents frameworks, but there are many others
SAE is the Society of Automotive Engineers.
SAE defines Communications Standard utilized in On-and Off-Road Land-Based Vehicles. In this schema 3 classes of communicating devices are explained:

CLASS A: up to 10Kbit/sec, multipurpose, asynchronous, used for non-realtime, smart sensors, wire reduction.
CLASS B: in the range 10Kbit/sec up to 125Kbit/sec, used for intermodule data transfer and non-realtime control. SAE J1850 is a CLASS B protocol, currently used for low-cost connectivity between nodes like instrumentation and diagnostic devices.
CLASS C: critical, high speed, realtime communications between device. For these needs, hi-speed CAN is currently used (up to 1Mbit/sec), but there are also faster alternatives, like Flexray (up to 10Mbit/sec, firstly implemented in BMW X7 X6 in 2008 see here).

SAE J1850 describes two different protocols: a low speed single wire VPW (Variable Pulse Width) protocol running at 10.4Kbit/sec and a faster two wire differential PWM (Pulse Width Modulation) protocol running at 41.6Kbit/sec. This is NOT CAN nor is it compatible with CAN.
VPW is classically used by GM (General Motors) vehicles.
PWM is classically used by Ford vehicles.

ISO_9141-2 is not a signaling protocol, but a diagnostic interface to check vehicle component functionality. It is a serial interface that runs at 9.6Kbit/sec. It is often available in OBD-2 connector.

ISO_11992 is a CAN bus used in trucks for communications between the tractor and the trailers.

SAE_J1939 is a set of specification based on an underlying CAN infrastructure, working with 29bit identifiers and usually with a bit rate of 250kbit/sec. This is normally used in trucks and industrial vehicles. It is a prerequisite for the FMS (see forward) system to work. An introduction to SAE_J1939 by Marcus Junger can be found on Vector site here. Other J1939 infos are on,. See also here, and here.
According to wikipedia, SAE_J1939 supersedes SAE_J1708 and SAE_J1587.

Here is a list of Automotive data buses, by Leroy Davis.

Vehicle Networks
Actually there are many vehicle networks, eventually based on different standards, different criticality, different protocols, and different communication speeds. Currently these networks are converging to the CAN standard, but there are many others. Since CAN is now the de-facto standard for vehicle networking, sometimes it is also identified as VDB (Vehicle Data Bus).
Despite its popularity, CAN bus is not the only network inside any modern vehicle, and in a single vehicle there are usually different networks (multiple CAN networks and NON-CAN networks).

CAN stands for Controller Area Network. It was originally developed by Bosch, starting in 1983. CAN is used in many automation environments and not only in automotive industry.

In a CAN bus all the communicating devices are connected to the same two wires, labeled CAN-High and CAN-Low. All the devices must use the bus at the same speed. At each end, the two wires are connected with a 120 ohm termination resistor. It is not required to have a common ground signal among the communicating devices. Bus maximum length is dependent from the operational speed, and at 1Mbit/sec is about 40m. Vehicle network bus speeds are usually below 500Kbit/sec. High speed bus vehicle implementation often adopt twisted pair wires.
In a normal situation, the two wires carry a two-level signal, perfectly specular, and whenever one is high the other is low. Here are two nice pictures (source: ) representing oscilloscope reading of the two wires of a CAN bus. The second image allow a clear understanding of the specular nature of the signals.

From these pictures, the different logical values of the signals can be read, and here each signal has a span of about 1V. In the upper picture, a full CAN packet transfer is visible. The overall packet transfer time is about 200ms (320-120).

Actual CAN bus voltages are not usually this neat.
Here is an actual example (this too from picoauto) (Voltage references seem nonsensical in this picture).

The CAN Protocol
Currently there are two main version of the CAN protocol
Standard CAN: 2.0A with 11bits identifiers
Extended CAN: 2.0B with 29bits identifiers
CAN is defined in ISO_11519 and ISO_11898.

ISO 11898-2 defines the high speed CAN, up to 1Mbit/sec
ISO 11898-2 high speed
ISO 11898-2 is the most used physical layer standard for CAN networks. It describes the bus access unit (implemented as CAN high-speed transceiver) functions as well as some medium-dependent interface features.
In this standard the data rate is defined up to 1 Mbit/s with a theoretically possible bus length of 40 m at 1 Mbit/s. The high-speed standard specifies a two-wire differential bus whereby the number of nodes is limited by the electrical busload. The characteristic line impedance is 120 Ohm, the common mode voltage ranges from -2 V on CAN_L to +7 V on CAN_H. The nominal specific propagation delay of the two-wire bus line is specified at 5 ns/m. All these figures are valid only for a 1 Mbit/s transfer rate and a maximum network length of 40 m.
In order to achieve physical compatibility all nodes in the network must use the same or a similar bit-timing. For automotive applications the SAE published the SAE J2284 specification. For industrial and other non-automotive applications the system designer may use the CiA 102 recommendation. This specification defines the bit-timing for rates of 10 kbit/s to 1 Mbit/s. It also provides recommendations for bus lines and for connectors and pin assignment.
ISO 11898-3 (aka ISO 11519-2) defines the fault tolerant (and lower speed) CAN, up to 125Kbit/sec
ISO 11898-3 fault-tolerant

An alternative form of bus interfacing and arrangement of bus lines is specified in ISO 11898-3 (fault-tolerant CAN). This standard is mainly used for body electronics in the automotive industry. Since for this specification a short network was assumed, the problem of signal reflection is not as important as for long bus lines. This makes the use of an open bus line possible.
This means low bus drivers can be used for networks with very low power consumption and the bus topology is no longer limited to a linear structure. It is possible to transmit data asymmetrically over just one bus line in case of an electrical failure of one of the bus lines.
ISO 11898-3 defines data rates up to 125 kbit/s with the maximum bus length depending on the data rate used and the busload. Up to 32 nodes per network are specified. The common mode voltage ranges between -2 V and +7 V. The power supply is defined at 5 V.
Transceiver chips, which support this standard, are available from several companies. The fault-tolerant transceivers support the complete error management including the detection of bus errors and automatic switching to asymmetrical signal transmission.

The preceding two quotes of text about CAN physical layer specifications are taken from here (fetched on dec 4 2010):
Also there are other physical layer standards.

The following section is shamelessly copied from Staffan Nilsson web page
(with some corrections)

ISO 11898-2 voltage levels  (CAN High Speed)

Signal recessive state dominant state unit
min nominal max min nominal max
CAN-High 2.0 2.5 3.0 2.75 3.5 4.5 Volt
CAN-Low 2.0 2.5 3.0 0.5 1.5 2.25 Volt

Note that for the recessive state, nominal voltage for the two wires is the same. This decreases the power drawn from the nodes through the termination resistors. These resistors are 120ohm and are located on each end of the wires. Some people have played with using central termination resistors (that is, putting them in one place on the bus). This is not recommended, since that configuration will not prevent reflection problems.

ISO 11519 voltage levels (CAN Low Speed)

Signal recessive state dominant state unit
min nominal max min nominal max
CAN-High 1.6 1.75 1.9 3.85 4.0 5.0 Volt
CAN-Low 3.1 3.25 3.4 0 1.0 1.15 Volt

ISO 11519 does not require termination resistors. They are not necessary because the limited bit rates (maximum 125 kB/s) makes the bus insensitive to reflections. The voltage level on the CAN bus is recessive when the bus is idle.

Bus lengths
The maximum bus length for a CAN network depends on the bit rate used. It is required that the wave front of the bit signal has time to travel to the most remote node and back again before the bit is sampled. This means that if the bus length is near the maximum for the bit rate used, one should
choose the sampling point with utmost care - one the other hand, one should always do that!

Below is a table of different bus lengths and the corresponding maximum bit rates.

Bus length (metres) Maximum bit rate (bit/s)
40 1 Mbit/s
100 500 kbit/s
200 250 kpit/s
500 125 kbit/s
6 km 10 kbit/s

According to the ISO 11898 standard, the impedance of the cable shall be 120 +- 12 ohms. It should be twisted pair, shielded or unshielded. Work is in progress on the single-wire standard SAE J2411.


CAN frames
Here are some informations about CAN data frames
the following picture is from
The Standard and Extended frames are shown, and the different address field length can be seen.

CAN reliability
CAN bus communications are usually very reliable, quite insensitive to external interferences (since external interferences affect similarly both wires, the difference between the voltages remains unchanged), and to single control unit fault. The devices can often work even in case of bus being severely miswired (one cable shorted to ground or to vcc). No need of a common ground also increases robustness. This reliability is among the properties that made it the current standard in difficult environments, with wide temperature ranges, and very varying environmental situations.

Detecting CAN
Since there are many wires, it is not easy to identify the proper ones.
0.CAN signals are usually not present if the key is not turned to power the dashboard. (It is normally not needed that the engine is powered).
1.CAN wires are usually twisted.
2.Checking CAN signal presence without the use of an oscilloscope: A simple test to see if the bus is operating correctly is to use a multimeter and measure the voltage between the two wires. In "perfect" situations, if the bus is active and working it will show a steady 2.5V or 0,5V (in absence of signal changes), or a quick alternance between 0,5 and 2,5V. If not working it will be 0V as one of the CAN controllers on the network is pulling the bus low (known as Bus Off).
3. Operating with a two channels oscilloscope, and using the subtract function between the two signals CAN-H and CAN-L, you should get a constant (because the two signals have opposite phases). Oscilloscope can also help in detecting the speed of the CAN bus signals. (will add details here).
4. An indirect CAN presence indicator could be testing for proper termination. Proper termination of a CAN bus can be easily tested with a multimeter: when the bus is not used, a resistance of 60ohm should be measured between the two cables (the two 120 ohms terminators in parallel at each side give a global resistance of 120/2=60 ohms).
5. As a useful tool for CAN detection check the Würth CANfinder device.
6. CAN signals could not be present where they should be (i.e. in the OBD2 connector) if a proper setting is not performed on the gateway device.

Interfacing with CAN
In term of circuitry, every device connecting to CAN bus usually interfaces via a CAN Controller, which in turn acceses the bus via a CAN line driver (actually a transceiver).

The CAN controller actually speaks with the device in some way (for example via a serial RS232 interface) and on the other Many manufacturers produce CAN line driver integrated circuits, for example Dallas Semiconductors/MAXIM MAX13050 or Microchip MCP2551.or Philips PCA82C250. or Philips/NXP TJA1054 

The following picture shows a generic CAN bus with some devices connected. Proper bus termination should be present at each bus end to damp electric signal reflection (echos). Also it is important to minimize length of the connection between the bus and the transceiver of each connected device (for minimizing undesired echo effects).

Modules are sets of ECUs
In a vehicle, a Module usually identifies a set of two or more Electronic Control Units.
Engine control being the first and most critical, the corresponding Control Units are the most complex. Engine Control Unit (ECU) is supported by Transmission Control Unit (TCU) and the two are sometimes referred as Powertrain Control Module (PCM). Transmission Control Unit, among other things, takes care of gear shift.

User related Electronic Control Units are often referred as a whole with the term Body Control Module or BCM .

Different Networks
The different criticality of the signaling among the vehicle electronic devices, created a push for insulating the networks of different modules, for security needs, but also due to different equipment interfaces being at different speeds.
These different networks are grouped in 3 main classes:
  1. Body Frame, requiring speeds up to 10Kbps (electric glasses, doors, etc,) [as example of BCM see later references to Peugeot BSI Built-in System Interface]
  2. Dashboard instrumentation, requiring speed range 50-125Kbps (instrumentation, air conditioning, etc.)
  3. Engine and powertrain, requiring high speed (up to 1Mbps)
    Some of these vehicle networks can also be non-CAN. There are other standards used in vehicle networks, like LIN (used for low cost, low speed, non critical use, see also here), FlexRay (used for high speed, critical needs, in BMW SUVs), MOST (Media Oriented System Transport) for multimedia and infotainment.

    Bus Separation

    Engine Control, Airbag, Braking subsystem, Speed control and ABS, are the most safety-critical systems, require high speed, and therefore are usually kept separated from less critical systems.

    The separation between the different CAN buses allow much more resilience of the critical systems in the case a noncritical control unit fails (the car engine still starts if you have a problem in the cd-player or in the cabin lights).

    Gateways between different networks
    In most vehicles, many CAN networks are there, operating at different speed, and that there are gateways allowing data being transferred among the different buses.
    The presence of these gateways allow filtered transfer of information, along with eventual speed change. A gateway could act as a firewall allowing only the propagation of specific packets. Gateways are actually electronic devices connected to more than one bus, and can be programmed to allow packet filtering.
    There is a interesting specification called Pass-Through SAE J2534-1 which is designed to allow a sort of common protocol (!!vendor and brand independent!!) for traversing in-between bus gateways (CAN and not CAN). This standard should be supported on all vehicles manufactured after 2004. Pass-through specification is targeted to reprogramming and re-flashing of individual electronic control units, but allows also read and write I/O, and periodic messages definition. There is also a set of defined APIs (Application to Program Interfaces) thru which the dialogue can be implemented.

    Here is the description of the SAE J2534-1 recommendation document, as taken from on sept 22, 2011.

    "This SAE Recommended Practice provides the framework to allow reprogramming software applications from all vehicle manufacturers the flexibility to work with multiple vehicle data link interface tools from multiple tool suppliers. This system enables each vehicle manufacturer to control the programming sequence for electronic control units (ECU's) in their vehicles, but allows a single set of programming hardware and vehicle interface to be used to program modules for all vehicle manufacturers. This document does not limit the hardware possibilities for the connection between the PC used for the software application and the tool (e.g., RS-232, RS-485, USB, Ethernet...). Tool suppliers are free to choose the hardware interface appropriate for their tool. The goal of this document is to ensure that reprogramming software from any vehicle manufacturer is compatible with hardware supplied by any tool manufacturer. The U.S. Environmental Protection Agency (EPA) and the California Air Resources Board (ARB) have proposed requirements for reprogramming vehicles for all manufacturers by the aftermarket repair industry. This document is intended to meet those proposed requirements for 2004 model year vehicles. Additional requirements for the 2005 model year may require revision of this document, most notably the inclusion of SAE J1939 for some heavy-duty vehicles. This document will be reviewed for possible revision after those regulations are finalized and requirements are better understood. Possible revisions include SAE J1939 specific software and an alternate vehicle connector, but the basic hardware of an SAE J2534 interface device is expected to remain unchanged."
    Check also this article by Dan DeMaggio from Drew Technologies: for the story of the development of this SAE recommendation.

    Here is an example of a CAN bus dual interface gateway device: the CAN/CAN Gateway CG-ARM7, manufactured by EMS Dr. Thomas Wünsche:

    Such a device is indeed a firewall with sophisticated packet content filtering and rewriting capacity.
    Here is a document describing a CAN gateway device in a Volkswagen Golf car
    The following two paragraphs are taken from

    The role of the Gateway (also known as the Data bus diagnostic interface J533) is the exchange of data between the CAN data bus systems (‘powertrain CAN data bus’, ‘convenience CAN data bus’ and ‘infotainment CAN data bus’) and the conversion of diagnostic data from CAN data bus systems to K-cable and vice versa so the data can be used by vehicle diagnosis, testing and information systems like the dealer VAS tools and Vagcom/VCDS.

    For various reasons including power drain issues with third generation head units or the addition of new unsupported modules the CAN bus gateway must be upgraded to a newer revision. This guide covers the replacement of the CAN bus gateway in a 2005 MY06 Volkswagen Golf GTI. The upgrade replaces the 1K0 907 530 E (1K0907530E) with a 1K0 907 530 AA (1K0907530AA).
    Here is a picture of the Volkswagen/Audi gateway (part no: 1K0907530AA), taken from

    This gateway in Volkswagen terms is called "Data bus diagnostic interface J533". It is used in many car models from this vendor. I found an Audi technical document (from Audi A5 owners group website Audi_A5_-_Networking_en_2.pdf) describing the 4 different version of this gateway component (differences are in terms of its interfaces), for different car models. It is connected to many different buses (different CANs, LIN, MOST). The document states that the "transport mode" can be activated on demand. I guess that this transport mode could allow  flow of information between the different buses thru the gateway itself (that in this mode acts somewhat like a router).
    Check also this webpage about J533 gateway.

    OBD: On Board Diagnostic
    Due to the progressive diffusion of electronic devices in the vehicle industry, also diagnostic procedures started to rely on querying these different pieces of electronics, for troubleshooting, and parameter tuning.
    The On Board Diagnostic (OBD) standards define how these diagnosis can be performed. Each Control Unit has a set of Diagnostic Trouble Codes (DTC) that can help in identifying its status or eventual failures.
    Actual diagnosis is performed by a technician connecting a probing device to a specific plug inside the vehicle, and performing analysis.
    In many vehicles, the OBD connector (currently usually compliant to OBD-2 standard) is within reach from the driver seat, and allows access to at least one of the vehicle CAN buses.

    Over the years, many different versions of the OBD standard appeared, and the most current one is labeled OBD-2 or OBD-II, which uses a female 16-pin (2x8) SAE J1962 connector on the vehicle. Here is the pinout of its female connector (from wikipedia).

    Specific gateway configurations could be needed so to allow specific Electronic Control Units traffic (filtering) to be available on the OBD-2 CAN interface. Also, depending on the manufacturer and model, CAN bus availability on the OBD-2 connector could require a specific configuration elsewhere (maybe jumpers in the circuit breaker panel).
    Being present in many vehicles, the OBD-2 connector usually allows access to many diagnostic signals. Sometimes more than one CAN bus is made available on the connector, on different pins.

    Here is the pinout of the FIAT OBD-2 connector:

    Some "rules" about the OBD-2 connector
    (info from and )
    If pin 5,6,14,16 are connected, the pins 6 and 14 are CAN-HI/LOW (ISO_15765-4  /  SAE_J2284), while pin 5 is ground and pin 16 is 12Vcc
    If pins 5,7,16 and optionally 15 are connected, the connector supports access to ISO_9141-2 (aka KWP): pin 5 is ground, pin 16 is 12Vcc, pin 7 is ISO-data (aka ISO_K-line), as well as optional pin 15 which is older ISO_9141-2 (aka ISO_L-line).
    If pins 2,5,16 are connected, the connector supports access to VPW_J1850: pin 5 is ground, pin 16 is 12Vcc, and pin 2 is VPW-data

    If pins 2,5,10,16 are connected, the connector supports access to PWM_J1850: pin 5 is ground, pin 16 is 12Vcc, and pin 2 and 10 are PWM-data

    Connector Pins 1,3,8,9,11,12,13 (if connected) are used differently from different vehicle manufacturers, and the OBD-2 standard does not define their role.

    Contact usage of some manufacturers (table from
    PinSAE J1979,
    ISO 15031
    since 5.2002
    1Manufacturer mandatedsecond UARTABS, Brakes, K-LinereservedSaab Instruments (+)SIR (GM8192 Prot.)SW-LS-CAN (33kB)
    DW-FT-CAN (+) (<125kB)
    2J1850 (+) PWM/VPWJ1850(+) VPWDW-FT-CAN(+)n/an/an/an/a
    3Manufacturer mandatedComfortAirbagK-Line, K2, TCM, Sunroof, CDL, Multi-Timern/aABS (KW81-Prot.)MS-CAN (+) (95kB)
    4Chassis groundChassis groundChassis groundChassis groundChassis groundChassis groundChassis ground
    5Signal groundSignal groundSignal groundSignal groundSignal groundSignal groundSignal ground
    6ISO 15765 HS-CAN (+)PCMISO 15765 HS-CAN(+)BlinkcodeBlinkcodeTCMISO 15765 HS-CAN (+) (500kB)
    7ISO 9141 K-Linen/aISO 9141 K-Line (engine)K-Line, K1 (engine)K-Line, K1 (engine)K-Linie, K1 (engine)n/a
    8Manufacturer mandatedCCMn/aK-Line, K4K-Line (Saab 9000/1, KW81/82 Prot.)n/areserved
    9Manufacturer mandatedfirst UARTBody ECUreserviertSaab Instruments (-)ECM/TCM (GM8192 Prot.)DW-FT-CAN (-) (<125kB)
    10J1850 (-) PWMn/aDW-FT-CAN (-)n/an/an/an/a
    11Manufacturer mandatedEVA Controller(Anti-Theft system)reservedL-Line Memory SeatsSIRMS-CAN (-) (95kB)
    12Manufacturer mandatedABSengine compartmentK-Line, K3, ABS, TC, Steering, RTD, OWn/aABSK-Line (KW82 Prot.)
    13Manufacturer mandatedSIRLuggage compartmentreserved f. K-Line, K5n/aECMreserved
    14ISO 15765 HS-CAN (-)E&CISO 15765 HS-CAN (-)reservedn/an/aISO 15765 HS-CAN (-) (500kB)
    15ISO 9141 L-Linen/an/an/an/an/an/a
    16Battery Plus, unswitchedBattery Plus, unswitchedBattery Plus, unswitchedBattery Plus, unswitchedBattery Plus, unswitchedBattery Plus, unswitchedBattery Plus, unswitched

    Accessing CAN bus in cars
    When CAN bus is not available in the OBD2 plug or it is not feasible to connect to that plug, or if the gateway is not "publishing" the CAN signals on the OBD2 port, the bus can be accessed simply connecting to its wires.
    But a disclaimer is needed:
    In most cases, car manufacturers are not disclosing the specifications of their diagnostic systems and there are no easy approaches that are consistant across the different brands. Even if you are able to access CAN signals, it will not an easy task to decode and understand the meaning of the data packets. Here is a guide (prepared by uk company Racelogic) in finding the right wires in different vehicles. Devices like the aforementioned Würth canfinder can also be useful.

    On Volkswagen Golf cars, the following wire color codes apply (from ). All the three CAN networks use cable pairs, and each pair can be identified by the color of the CAN-HIGH wire, being all the CAN-LOW wires of the same color.

    An unshielded two-wire line (1) and (2) with a cross section of 0.35 mm² or 0.5 mm² is used for CAN bus wiring.
    The colour codes of the CAN bus wiring are:
    Powertrain CAN high wire Orange/black
    Convenience CAN high wire Orange/green
    Infotainment CAN high Orange/violet
    CAN low wire, (all) Orange/brown
    On FIAT punto diesel, we found a CAN signal in the connector behind the radio. The CAN wires in this car are pink-black and pink-white.
    the following link describes a project to interface a car CAN bus to a wifi network:

    For Peugeot (/PSA and probably for cytroen) cars, check this site: where you can find accurate information and Complete Wiring diagram for Peugeot307, along with information about BSI (Body Control: Built-in System Interface)
    Peugeot BSI is connected and "coupled" to Engine Control Unit, and there are protections to avoid tampering by non official dealers or auto-repair technicians. Here are a set of warnings related to Peugeot BSI-ECU maintenance:,3.0.html
    Here is a picture of a Peugeot BSI.
    Peugeot/PSA cars used to implement their own version of CAN bus, called VAN (Vehicle Area Network Comfort data VAN bus / Body Control Data bus). I found some clever guys who did some awesome job in collecting information about VAN: Graham Auld, and Alessandro Zummo. Check and I got to these sites via this webpage.

    Accessing CAN in trucks
    Specifically for trucks, there is another standard, to have a uniform access to vehicle data, and targeted for the needs of driving monitoring devices.

    This FMS (Fleet Management System) standard is very important for allowing access to specific truck information like the tachometer and odometer, which are needed to be read in the devices to control the driver activity (digital tachographs). FMS requires a SAE J1939 CAN 29-bit 250kbit/sec underlying standard.

    For european digital tachographs, check
    In order to be compliant with FMS standard, truck manufacturers implement a specific gateway ECU which reads the informations required by the standard from all the suitable places and thru all the required standard, complying with internal vehicle-brand-specific protocols, and makes all these informations available thru a specific CAN bus to which the tachometer device is connected.
    In this way, an FMS compliant digital tachometer devices can be easily connected to any FMS compliant truck.

    Different connection cables

    (this section needs work and it is partially outdated by what I wrote in the OBD-2 connector section)

    A number of different ready made cables exist to access car diagnostics, usually via the aforementioned ODB-2 connector
    here is a list of their names, but I am far from understanding their differences

    SAE J1850 (can be a dual wire differential 41.6 Kbit/s PWM -Pulse Width Modulation-, or a 10.4Kbit/s VPW singlewire -Variable Pulse Width- ). see this intel document.
    SAE J2534 (this is a PWM protocol used in Ford, Lincoln, Mercury, Mazda vehicles)

    K-LINE and L-LINE (ISO 9141-2) (to be explained: i need to study)
    ISO 14230-4 (also known as KWP)

    HS-CAN (iso 15765)

    VAG-COM is not a cable, but a product by Ross-Tech. It is a diagnostic windows software for Volkswagen/Audi. Some cables to be used with this software are labeled VAG-COM

    ELM 32x are integrated circuits, (here is elm327 description), sold by and based on Microchip Technology Inc. raw devices. These ELM chips act as generic ODB2 decoders and are able to identify and decode many of the different signals available on the ODB2 plug, converting them to RS232, suitable for connection to a PC. Many different PC diagnostic software are capable of interfacing with car electronics via an ELM based adaptor, like this

    (To Be fixed)

    Arduino and CAN
    It is possible to interface an Arduino 2009 board with CAN bus, via a specific CAN shield
    I successfully used SkPang Arduino CAN-Bus Shield, to connect to an Audi A6 (2003) and I was able (using the provided sample application) to successfully read RPM (revolutions per minute) data from the engine using a polling mechanism.

    This shield uses a MCP2515 CAN controller and a MCP2551 CAN line driver.

    Here is a typical configuration of MCP2551
    We are currently working on improving the code provided with the shield so to have more sophisticated functions.

    Oct 2011 Note: As Rick (in an anonymous comment) said, Sk-Pang shield uses a library taken from Fabien Greif code ( here is the main site: ).The code can be improved, and I hope I will have some time to dedicate to this.

    This is a project, started in 2009, to use a custom Arduino-like board to interface to car CAN-Bus and build a
    The project is described in this wikipedia page: and the code repository, along with some pictures of prototypes, is in a google-code page, here:

    This project is targeted to build a fuel measurement computer, with an Arduino like device, analyzing the impulses to the fuel injectors, and having tables for calculating the specific fuel injected basing on impulse duration. The signals have to be directly read/taken from the main engine ECU connections to the fuel injectors. Data appears extremely accurate. Here is the link:

    Teltonika FM4200
    This is a device specifically designed to interface with FMS CAN interface in trucks.
    I am also testing this device, which uses a NXP LPC2368 microcontroller which is (incidentally) the same uc used by the mbed project. Here is some info about the microcontroller which includes a CAN controller (but not a CAN transceiver). The FM4200 circuits utilizes a Texas Instruments SN65HVD234D 3.3V CAN transceiver. I will write more about this device, as soon as I will have performed more thoroughful tests.

    CAN Bus data reverse engineering:
    For a Toyota Prius car, by Attila Vass:
    For a SAAB car by Tomi Liljemark:

    General References and links
    The great CAN-CIA site: which is probably the best and more reliable reference site available.
    The CAN dictionary:  contains a definition of most of the acronyms and abbreviations.

    Staffan Nilsson's great page about CAN:
    Bosch CAN 2.0 specifications.
    Mike J Schofield pages: (non working url: - there is a mirror in Staffan Nilsson site)

    CAN analysis and equipment vendors : I bought an EMS-Wuensche CPC-USB/ARM7 with galvanic optoinsulation and lowspeed transceiver (TJA1054) for automotive. Received the object (2010.dec.10), and first impression is good: seems very well built and reliable. Will soon test it on the field.

    CAN bus in motorcycles
    Of course, also motorcycles electronic utilizes digital protocols.
    Here is a page about CAN bus in BMW motorcycles.

    An affordable and cheap Oscilloscope
    Actually I ordered this Rigol DS1052E, but I am still waiting the device to arrive.
    Will be able to report on its features, as soon as I evaluate it.
    Here are informations about the scope:

    FiatECUScan is a software for analyzing Italian made cars (fiat/alfa/lancia branded). Comes in free version and in paid version, with different features. Here is a list of the vehicles supported by current version of FiatECUScan.

    FAQ: Q&A 
    Here are some questions I received by email and the answers I sent.

    Q: Is it possible to read value of XXX connecting to the can bus of my car?
              As quick answer I would just say that it is not possible. 

    But this impossibility is normally not due to physical reasons. Each ECU manufacturer uses its own set of rules & codes to craft data packets on their vehicles networks. These informations and data formats are not readily available, and there are no shared rules followed by different manufacturers.
    Fm4200 is designed to be able to decode FMS CAN, which is a standard data format representation accepted and shared by all industrial vehicles (trucks). The target is to allow tachometer interconnect with vehicle dashboard.
    Tachometers are devices that in many countries MUST be installed on trucks so to monitor driver behavior and work activities. Since there are many tachometer devices, which are built and installed by many countries certified suppliers, a standard was needed, so FMS was born. Non-professional access to tachometer data connection is generally prohibited. 
    Thru car databus reverse engineering techniques, mostly based on trial and error and/or leaked informations, it is theoretically possible to map some of the CAN data packets to their meanings. Generally read only approach is safe. But problems could arise when vehicle software maintenance is performed, because data packet meaning could change, and current manufacturers are not expected to openly disclose these details. 
    Write access to the drivetrain and engine bus is to be considered critical and is generally explicitely forbidden or strongly not recommended. 
    For sure it could be great if all the data was understandable and accessible, but there are important security implications if people irresponsibly tamper with these things. Vehicle security, insurance coverage and road safety could be impacted. 
    So, be careful and play always on the safe side.
    My suggestion is to NEVER connect untrusted devices, unknown or potentially unreliable closed source software to critical systems. 
    Always study, learn and understand before playing. And always share responsibly your discoveries.



    Marco (@mgua on Twitter)


    Tuesday, September 28, 2010

    miss purr

    Family has a new member: miss purr. She was born on sept 22 2010.
    She had a brother who unfortunately died at birth.

    isn't she cute?

    Here are some new pictures, taken some weeks later:


    Sunday, September 12, 2010

    Smile and be happy

    Here is one of the nicest clip I ever found on youtube

    "Validation" is a fable about the magic of free parking.
    Starring TJ Thyne & Vicki Davis.
    Writer/Director/Composer - Kurt Kuenne.

    Winner - Best Narrative Short, Cleveland Int'l Film Festival, 
    Winner - Jury Award, Gen Art Chicago Film Festival, 
    Winner - Audience Award, Hawaii Int'l Film Festival, 
    Winner - Best Short Comedy, Breckenridge Festival of Film, 
    Winner - Crystal Heart Award, Best Short Film & Audience Award, Heartland Film Festival, 
    Winner - Christopher & Dana Reeve Audience Award, Williamstown Film Festival, 
    Winner - Best Comedy, Dam Short Film Festival, 
    Winner - Best Short Film, Sedona Int'l Film Festival.

    I like the idea and the music, and the actors.

    I smiled.

    Did you?

    marco (@mgua on twitter)


    Wednesday, September 1, 2010

    Hitec Aurora9

    I received my new Aurora 9 RC transmitter yesterday, and I am very excited about its features.

    I am a long time owner of Hitec Optic 6 and before buying the Aurora9 I was evaluating also the Futaba T10CG. The Futaba was more expensive, and also more common in my local group of RC modelers, but is lacking the telemetry features that are very interesting for me.

    In the coming weekend I will test it on the fly field.

    My new Aurora has firmware release 1.06, as seen from the info menu of the system panel.
    I also ordered HPP-22 device for connecting radio to pc and also the HTS-SS Sensor Station, but these components are still to arrive.

    First Impressions
    I found the device extremely easy to setup. There is a great wizard for setting up all the model features. It is really easy and quick. Great improvement over the Optic 6 menus that I found quite clumsy and not intuitive.
    Radio pairing is straightforward. Touch Screen is simply great. Screen is large and allows quick check of all the trim settings. Subtrims and EPAs (End Of Paths)are just two taps away.
    It would be nice to have some front indicators of the state of the two leds on the Spectra AFHSS module. Those leds on the back are simply impossible to check while piloting.

    I am excited about its telemetry features, and I am planning to study the protocol used between the sensors and the receiver. I think it could be an I2C protocol. Will definitely try to find some more information.
    The basic idea would be to decode the protocol so to add my own sensors on the plane, and to send to the pilot the collected data via the receiver data port thru the downlink channel.

    I want a Datalogger!
    My idea is to build a small datalogging interface device to be used at fly field, to be connected to the data port of the spectra AFHSS module, so to log telemetry data to flash memory.
    The flash memory could then be read on the pc.
    I think that such a project could be very useful for Hitec Aurora9 users, and eventually for other telemetry capable radio systems..

    About reverse engineering of HPP-22:
    Telemetry forum on RC Model Reviews:

    Will keep this post up to date with my new discoveries...

    Marco (@mgua on twitter)


    Saturday, June 5, 2010

    Issues with Lotus Domino 8.5.1 64bit on Windows 2008 64bit

    We experienced significant issues with windows 2008 64 and IBM Lotus Domino 8.5.1, despite the platform being officially certified:

    The biggest problems were related to problems in closing the lotus domino server. The servers took ages to shutdown, and the processes were blocked in (apparently) a kernel race condition in the network interface card drivers (we had a significant percent of the cpu time being spent in the system kernel).

    Installing FP1 or FP2 did not help.These malfunctions were completely unrelated to DAOS features.

    We also observed some errors probably related to the java subsystem used by the domino server.
    A typical symptom was that the domino server console was not closing after the "Server Shutdown Completed" message, and additional logs were still printed, without the server going down. The server restart time was completely unreliable despite the setting in the transaction log configuration to "favor restart time".

    The problems completely disapperared after complete reinstallation on windows 2003 64, and currently we are satisfied of the performance and stability of our Rome Domino 64 bit Installations. To our knowledge there are currently no particular domino related benefits in using windows 2008 64 bit envronments instead of Windows 2003/64.

    We did not perform any specific registry tweaking on the current domino production servers. We are currently running Domino Release 8.5.1FP2 HF55 on Windows/2003/64 5.2 on most customer installations.

    Further analysis that we performed on another customer, later, pointed out a possible cause of this problem related to the windows 2008 drivers of the broadcom network cards.

    On a small customer with a windows 2008 64 bit domino installation we performed the aforementioned changes in the broadcom nic parameters, and since then we had the domino server running flawlessly.
    Both installations are using servers with on-board broadcom network interface cards.

    We are not currently recommending lotus domino 64 bit installations on windows 2008 64.
    Broadcom gigabit devices are currently used by many server producers (HP, DELL, SIEMENS just to name a few).
    The reliability of these installations will probably change in the near future, with new fixes being delivered by both IBM and Microsoft.

    We can not be 100% sure that the Broadcom issue was the exact (or only) cause of the troubles we had, but the evidences are quite strong.

    Another potential issue to be aware of is the use of Windows NTFS compression which seem to generate console errors and attachment access problems from webmail if used in conjuction with DAOS. This is not a commonly adopted production solution, but we observed the problem during a migration transition.

    Marco (@mgua on twitter)


    Sunday, May 23, 2010

    Arduino in datacenter rack environmental monitoring

    TOMBOX* : An Arduino based solution for 
    environmental monitoring of datacenter racks

    Marco Guardigli  - TomWare -  
    started 2010 may 23
    last updated 2011 nov 18 (pictures added)

    *it was monbox, but conflicted with another project.


    Build a cheap and simple data collector and alerting system to monitor a set of server and network racks in a datacenter, via ethernet network. Project requires sensors for temperature, humidity, liquid spills, vibrations, door openings, ecc...


    Engineer and build a small box, including an Arduino with ethernet shield, some visible leds, a local power supply, and sensor connections. Each rack will have its box, and these will be connected to an autonomous monitoring vlan.
    A central Zabbix system will collect data from the boxes, manage historical series, and eventually generate alerts via email and sms (sms are sent via a bluetooth connection to a dedicated cellphone, so to be independent from main network availability)

    Project state:

    Underway, with prototype already working.


    We are using Arduino 2009 boards, with ethernet shields.
    Due to the arduino integration with ethernet shield, some pins are not available.

    The available pins are:
    Digital pins 2-9 (total 8 lines)
    Analog pins 0-5 (total 6 lines)

    Network Addressing:

    Each box needs to have a unique mac address and ip address. To keep circuit simple and avoid dip switches, we decided to "burn" this configuration directly on the code. Each box gets a personalized code, which differs just for mac and ip address configuration. The code is uploaded to each box via usb interface, upon setup. The address is then written on a label on each box.
    We discarded the option of implementing dhcp, because in any case we would have needed a software definition of a unique mac address.


    Each unit is powered via a small and cheap USB power supply, to be connected to the local rack power. (here is a picture of the power supply)


    We are planning to connect to each environmental monitoring box the following sensors:

    Front Rack Door: open/close, with a simple switch, on a digital pin.
    Back Rack Door: open/close, with a simple switch, on a digital pin.

    Temperature & Humidity: Here I have some options, and I have to choose the best one.
    • Temperature Option1: a simple thermistor, to be connected to an analog pin, in parallel with a resistor. This is very cheap, but requires calibration.
    • Temperature Option2: a National LM35 sensor, to be connected to an analog pin. This is cheap, and should be linear, with 0,5 °C accuracy which is ok for me. This should be ok if I put the sensor in the box itself.
    • Temperature Option3: a Dallas Semiconductor DS18S20 digital thermometer sensor, to be interfaced via 1-wire protocol a digital pin. This also has 0,5 °C accuracy, and should allow to use a longer cable and have the sensor at a longer distance from the box. I am afraid this is not going to be cheap.
    • Temperature + Humidity Option 1: a Sensirion SHT1x. This is a digital sensor that reads both temperature and humidity. It is already calibrated. I am afraid this is not going to be cheap, but there are many variants of this sensor, from the low-end SHT10 to the high-end SHT75. I need to ask about prices.
    • Temperature + Humidity Option 2: I found the Kele/Precon HS2000V which is an analog sensor that reads both temperature and humidity. This could be connected to two analog pins, and requires power. I could embed this sensor in the box itself.
    I decided to go on using a Sensirion SHT-11 digital sensor. It is a very small device, quite sophisticated.
     The quite difficult part was to solder it, because the contacts are very small and close each other. Also the device is quite delicate, and soldering has to be done quickly not to damage it.

    I built a simple sensor, made of two components: an infrared led, and an infrared photodiode. The infrared photodiode is mounted about 5cm apart from the led, and I put a heat shrinking tube on it. The resistor for the infrared led and for the photodiode are selected so to allow a "weak" reading which is altered by smoke on the ir path.

    The photodiode output is sampled in an analog input. In this way, if some smoke gets in the middle, the output will change, and it can be detected.

    I have to find (or maybe build) the proper sensor.

    Current Prototype:

    Actual product, as delivered to the customers
    The Arduino 2009 with atmega328, the wiznet ethernet shield, and a small hand made custom shield for our circuitry, have been packaged in hand made boxes.
    I choose Simona sheet 6mm and 3mm (a PVC foam material used in building and for making signs, also called FOREX or FOAMEX) as the material for the boxes. It is quite cheap.

    It is easy to cut, easy to glue, and has enough rigidity to allow screws. This material is fire resistant, easy to work and well suited for its strenght.


    As of november 2011, some dozens of these box have been built, and they work seamlessly in several datacenter environments.


    I already hacked something which is working, at least to perform some tests with the zabbix central sampling engine. Each Arduino box runs a webserver, which is providing in its page the reading of all the sensors.
    On the Zabbix server, there is a polling process and a parser which decodes the data, and archives it, eventually generating alarms.

    I will update the code posted here as soon it is a bit more refined.
    Here you have the code that runs on the arduino, to read the reed sensors (digital pin 4), and the temperature and humidity sensor (via digital pins 5 and 6). Reed sensors are to be put in series, so whatever is open triggers the door open alarm.

    Analog pin 0 will be used for smoke sensor, but code is not yet here.
    Digital pins 2 and 3 are used to briefly flash two colored leds, that in the future will become the box visual interface.

    (CAVEATS: the following source code has been copied and pasted from the IDE to the blog, and this process unfortunately changed a bit some code lines, when they contain HTML tags. Beware!)

     * Arduino + Ethernetshield (Wiznet)
     * datacenter sensor box
     * TOMBOX
     * Marco Guardigli 
     * this code is GPL, see
     * see
     * developed on arduino 21 ide, oct 2010.
     * based on arduino Web Server example code
     * SHT-11 portions shamelessly adapted from the following sources
     *   and
     * sensor reading happens when http request comes in.
     * sensors are not read if there are not incoming http requests
     * It works this way so to have a central monitoring software to 
     * perform http reads
     * in the future snmp trap to a remote server will probably be added
     * as well as polling independent sensor readings
     * components:
     *   reed magnetic sensor (on digital pin 4)
     *   sensirion sht-11 temp+humidity sensor (digital pins 5,6)
     *   home made smoke sensor, with infrared led and photodiode analog output (on analog pin 0)
     *   free digital i/o: 7,8,9
     *   free analog i/o: 1,2,3,4,5
     * Pin Connections (SHT-11 pin count starts from top left going down: the right pins are not connected)
     *      SHT-11  -  arduino netshield
     *      1 gnd   -  gnd
     *      2 DATA  -  digital 6
     *      3 SCK   -  digital 5
     *      4 VDD   -  5V
    #define DATA    6              /* Arduino pin for SHT11 data read/write */
    #define CLOCK   5              /* Arduino pin for toggling the clock */
    #define NOACK   0               /* Flags to tell read_byte routine whether */
    #define ACK     1                /* or not to send an ACK after the read   */ 
    /* Define the SHT1x commands to be their command codes */
    #define         MEASURE_TEMP    0x03
    #define         MEASURE_HUMI    0x05
    #define         STATUS_REG_W    0x06
    #define         STATUS_REG_R    0x07
    #define         RESET           0x1e
    /* Following constants are in microseconds */
    #define         LONG_DELAY      delayMicroseconds(50)
    #define         MEDIUM_DELAY    delayMicroseconds(10)
    #define         SHORT_DELAY     delayMicroseconds(5)
    unsigned char debug;          /* When set, intermediate data is printed */
    #define ALERTLED    2    /* bicolor led, RED, on if LOW */
    #define OKLED       3    /* bicolor led, RED, on if LOW */
    #define OKBLINK     20000 /* loops for OK led blink */
    #define ALERTBLINK  3000  /* loops for OK led blink */
    int i;
    byte mac[] = { 0xDE, 0xAD, 0xBA, 0xEF, 0x00, 0x01 };
    byte ip[] = { 172, 30, 4, 177 };
    Server server(80);
    int okcnt = OKBLINK;
    int alertcnt = ALERTBLINK;
    int okledstate = LOW;     /* led is on if state is LOW */
    int alertledstate = HIGH; /* led is on if state is LOW */ 
    int alert = false;        /* this goes true if we are in alert state. When this is true, alert led blinks */
     * sWriteByte
     *      Routine to write a byte to the SHT1x and check for the acknowledge
     * Parameters:
     *      @value          byte value to be written
     * Returns:
     *      0 for success, 1 if no Acknowledge received from SHT1x
    char sWriteByte(unsigned char value)
        unsigned char ix;                   /* loop index */
        unsigned char error;                /* result of the write */
        pinMode (DATA, OUTPUT);
        for (ix = 0x80; ix; ix >>= 1) {
            digitalWrite (DATA, ix & value);/* Next bit to I/O port */
            SHORT_DELAY;   /* Shouldn't be needed */
            digitalWrite (CLOCK, HIGH); /* Set clock signal high */
            MEDIUM_DELAY;   /* some delay needed */
            digitalWrite (CLOCK, LOW); /* Set clock back to low */
        pinMode (DATA, INPUT);              /* Prepare to read the ACK bit */
        digitalWrite (DATA, HIGH);          /* Engage pull-up resistor */
        digitalWrite (CLOCK, HIGH);         /* Send 9th clock for ack) */
        error = digitalRead (DATA);         /* Expect pulled down by SHT1x */
        digitalWrite (CLOCK, LOW);          /* complete the clock pulse */
        return error;
     * sReadByte
     *      Routine to read one byte from the SHT1x.  An acknowledge may or
     *      may not be generated, according to the routine's argument.
     * Parameters:
     *      @sendAck        If non-zero, an ACK is sent to the SHT1x if
     *                      the read was successful.
     * Returns:
     *      The value read from the SHT1x
    char sReadByte (unsigned char sendAck)
        unsigned char ix;                   /* loop index */
        unsigned char val = 0;              /* for building the received data */
         *  Note to Bill:   we should assure DATA is input by default
         *                  and get rid of these next two lines
        pinMode (DATA, INPUT);              /* Set data pin for input mode */
        digitalWrite (DATA, HIGH);          /* Engage pull-up resistor */
        for (ix = 0x80; ix; ix >>= 1) {
            digitalWrite (CLOCK, HIGH);     /* High tells SHT1x we're reading */
            if (digitalRead (DATA))
                val |= ix;                  /* If DATA high, set corr. bit */
            digitalWrite (CLOCK, LOW);      /* Tell SHT1x ready for next bit */
        pinMode (DATA, OUTPUT);             /* Change mode to prepare for ack */
        digitalWrite (DATA, !sendAck);      /* Set DATA LOW if sendAck requested */
        digitalWrite (CLOCK, HIGH);         /* Let SHT1x get the data */
        MEDIUM_DELAY;                       /* delay for safety */
        digitalWrite (CLOCK, LOW);          /* Signal we're done with this */
        pinMode (DATA, INPUT);              /* Return Arduino pin to input */
        digitalWrite (DATA, HIGH);          /* And engage the pull-up */
        return val;
     * sTransmitStart
     *      Routine to generate a "Transmission Start", which looks like:
     *                      _______           _______
     *              DATA:          |_________|
     *                            ____      ____
     *              CLOCK:  _____|    |____|    |____
     * Parameters:
     *      None
     * Returns:
     *      No return value.
    void sTransmitStart (void)
        pinMode (DATA, OUTPUT);             /* Set DATA mode output */
        digitalWrite (DATA, HIGH);          /* Start DATA in high state */
        digitalWrite (CLOCK, LOW);
        digitalWrite (CLOCK, HIGH);
        digitalWrite (DATA, LOW);
        digitalWrite (CLOCK, LOW);
        digitalWrite (CLOCK, HIGH);
        digitalWrite (DATA, HIGH);
        digitalWrite (CLOCK, LOW);
        /* This routine will normally be followed by a write, so leave pinMode */
     * sConnectionReset
     *      Routine to generate a transmission reset, i.e. reset the SHT1x
     *      to a known state to begin a transmission.  It produces a pulse
     *      train that looks like this:
     *         _____________________________________________________         _____
     *   DATA:                                                      |_______|
     *            _    _    _    _    _    _    _    _    _        ___     ___
     *   SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |___
     * Parameters:
     *      None
     * Returns:
     *      No return value.
    void sConnectionReset (void)
        unsigned char ix;
        pinMode (DATA, OUTPUT);             /* Set Data to output mode */
        digitalWrite (DATA, HIGH);          /* Start Data in high state */
        digitalWrite (CLOCK, LOW);          /* Start Clock in low state */
        /* Now generate 9 clock "pulses" */
        for (ix = 0; ix < 9; ix++) {
            digitalWrite (CLOCK, HIGH);
            digitalWrite (CLOCK, LOW);
        sTransmitStart ();                  /* Follow with start pulse */
     * sSoftReset
     *      Routine to do a "soft" reset, i.e. send a "Reset" command to the SHT1x
     * Parameters:
     *      None
     * Returns:
     *      0 for success, 1 if bad response from SHT1x
    char sSoftReset (void)
        sConnectionReset ();                /* Reset SHT1x communication */
        return sWriteByte (RESET);          /* Send command and return result */
     * doCRC
     *      Routine to calculate the CRC while message is sent / received
     * Parameters:
     *      @ch             character to be added to CRC
     *      @crc            crc to which character is to be added
     * Returns:
     *      Target CRC value is updated
    #define CRC_POLY        0x31            /* CRC polynomial x**8 + x**5 + x**4 */
    void doCRC (unsigned char ch, unsigned char *crc)
        int ix;
        unsigned char b7;
        for (ix = 0; ix < 8; ix++) {
            b7 = ch ^ *crc;
            *crc <<= 1;
            ch <<= 1;
            if (b7 & 0x80)
                *crc ^= CRC_POLY;
     * sMeasure
     *      Routine to make a measurement of either temperature or humidity, and
     *      return the result.
     * Parameters:
     *      @pValue         pointer to where value should be stored
     *      @command        command to be sent to the SHT1x
     *      @singleFlag     Flag to show a single byte only should be read
     * Returns:
     *      Returns the status from the 'read' of the data, and places the value
     *      read into the the locations pointed at by the arguments.  Note that the
     *      SHT1x returns data as (MSB, LSB) so this routine stores the
     *      (short integer) value in reverse sequence.
    char sMeasure (unsigned char *pValue, unsigned char command,
                   unsigned char singleFlag)
        unsigned char error;                /* holds return value from routine */
        unsigned int ix;                    /* used for 'wait for data' loop */
        unsigned char ch, crc, revCRC;
        crc = 0;                            /* Initialize CRC to zero */
        sTransmitStart ();                  /* Start transmission of command */
        error = sWriteByte (command);       /* Send the requested command */
        /* Note that sWriteByte leaves DATA in input mode */
        doCRC (command, &crc);              /* Include command in CRC */
        if (debug) {
            Serial.print("After 'command': CRC is 0x");
            Serial.println(crc, HEX);
        for (ix = 0; ix < 65535; ix++)
            if (!digitalRead (DATA))
        if (digitalRead (DATA)) 
             Serial.println("DATA did not go low after writing command");
        if (!singleFlag) {                  /* If a 2-byte reply */
            ch = sReadByte (ACK);           /* Read MSB of data */
            doCRC (ch, &crc);               /* Include in CRC */
            if (debug) {
                Serial.print("After MSB: CRC is 0x");
                Serial.println(crc, HEX);
            *(pValue + 1) = ch;             /* Store MSB byte */
        ch = sReadByte (ACK);               /* Read LSB of data */
        doCRC (ch, &crc);                   /* Include in CRC */
        *pValue = ch;                       /* Store LSB byte */
        if (debug) {
            Serial.print("After LSB: CRC is 0x");
            Serial.println(crc, HEX);
        ch = sReadByte (NOACK);             /* Read msg CRC, don't send ACK */
        revCRC = 0;
        for (ix = 0; ix < 8; ix++) {
          if ((0x80 >> ix) & ch)
            revCRC |= (1 << ix);
        if (debug) {
            Serial.print("After Checksum: CRC is 0x");
            Serial.print(crc, HEX);
            Serial.print(", received value was 0x");
            Serial.println(revCRC, HEX);
        if (crc != revCRC) {
            Serial.print("CRC error in reply (command was 0x");
            Serial.print(command, HEX);
            Serial.print("CRC is 0x");
            Serial.print(crc, HEX);
            Serial.print(", received value was 0x");
            Serial.println(revCRC, HEX);
            Serial.println(") - resetting SHT1x connection");
        return error;
     * calcTempHumid
     *      Routine to calculate the "true" temperature and humidity based upon
     *      the "tick" values read from the SHT1x.  The SHT1x is set to operate in
     *      12-bit mode for humidity, and 14-bit mode for temperature.  The
     *      conversion constants are taken from the SHT1x datasheet, assuming a
     *      supply voltage of 5.0V.
     * Parameters:
     *      @pHumidity      pointer to humidity value
     *      @pTemperature   pointer to temperature value
     * Returns:
     *      Input values of temperature and humidity are overwritten with their
     *      calculated "true" values.
    void calcTempHumid (float *pHumidity, float *pTemperature)
        /* Constants for conversion of reading to relative humidity */
    #define         C1      -4.0
    #define         C2      +0.0405
    #define         C3      -0.0000028
        /* Constants for temperature-compensated relative humidity */
    #define         T1      +0.01
    #define         T2      +0.00008
        /* Constants for conversion of temperature reading to Centigrade */
    #define         D1      -40.00
    #define         D2      +0.01
        float rh = *pHumidity;      /* relative humidity (input value) */
        float rhLin;                /* Linear value of humidity */
        float rhTrue;               /* Temperature-compensated humidity value */
        float t = *pTemperature;    /* input value for temperature */
        float tC;                   /* Temperature converted to Celsius */
        tC = D1 + (t * D2);         /* Linear conversion of temperature */
        rhLin = (C3 * rh * rh) + (C2 * rh) + C1;    /* "ticks" to relative H */
        rhTrue = (tC - 25) * (T1 + (T2 * rh)) + rhLin;
        /* Assure our relative humidity isn't out of range (> 100% or < 0.1%) */
        if (rhTrue > 100.0)
            rhTrue = 100.0;
        else if (rhTrue < 0.1)
            rhTrue = 0.1;
        /* Finally, return the calculated values */
        *pTemperature = tC;
        *pHumidity = rhTrue;
     * calcDewPoint
     *      Routine to calculate the dew point based upon relative humidity
     *      and temperature.  I have no idea what it's doing, but since it
     * comes from the Sensirion literature, it's probably correct :-).
     * Parameters:
     *      @humidity       value of relative humidity
     *      @temperature    value of temperature
     * Returns:
     *      Calculated dew point
    float calcDewPoint (float humidity, float temperature)
        float logEx;
        logEx = 0.66077 + (7.5 * temperature) / (237.3 + temperature)
                + (log10(humidity) - 2);
        return (logEx - 0.66077) * 237.3 / (0.66077 + 7.5 - logEx);
     * splitFloat
     *      This routine takes a float as input and returns the integer part and
     * the fractional part, to the number of decimal places specified.  The
     * only reason I wrote it is because I couldn't find any existing routine
     * to print out a float in a reasonable format (with decimal places)
     * Parameters:
     *      @fNum        The floating point number to be dissected
     *      @pInt        Pointer to an integer to contain the integer part
     *      @pFrac       Pointer to a string to contain the fraction
     *                   Note: the caller must assure the string is large enough
     *      @decPlaces   Number of decimal places for the operation
     * Returns:
     *      The values calculated are placed in the locations specified.
    void splitFloat (float *fNum, int *pInt, char *pFrac, int decPlaces) {
         int ix;
         int frac;
         float fVal;
         /* Round the input according to precision, plus fudge for noise */
         fVal = *fNum + (0.5 * pow(10.0, (float)(-decPlaces))) + 0.00001;
         *pInt = fVal;          /* Return truncated integer value */     
          * Now isolate just the fractional part of the original number
         fVal = fVal - (float)(*pInt);  /* Remove the integral part */
         /* Convert the fraction into a simple integer */
         frac = fVal * pow (10.0, (float)decPlaces);
         /* Now format it as a leading-zero string of digits */
         pFrac += decPlaces;    /* point to string terminator position */
         *pFrac-- = 0;          /* put in terminator */
         for (ix = 0; ix < decPlaces; ix++) {
             *pFrac-- = (frac % 10) | 0x30;  /* put in digits in reverse order */
             frac /= 10;
     * printReading
     *      Routine to print out the value of caculated data, using a common format
     *      of {label} {int value}.{single digit fraction}{suffix}
     * Parameters:
     *      @label          string for starting label
     *      @pVal           pointer to float value to display
     *      @suffix         string to append to value
     * Returns:
     *      nothing
    void printReading (char *label, float *pVal, char *suffix) {
        int num;
        char str[10];
        splitFloat (pVal, &num, str, 1);
        Serial.print(num, DEC);
    void loop2()
        char cmd;                   /* command input by user */
        int humidVal;               /* humidity value read from SHT1x */
        int tempVal;                /* temperature value from SHT1x */
        unsigned char statusVal;    /* contents of status register */
        float fHumidity;            /* working value for humidity calculation */
        float fTemperature;         /* working value for temperature calculation */
        float dewPoint;             /* calculated Dew Point value */
        unsigned char error;        /* return value for routine calls */
        while (Serial.available() > 0) {  /* when a serial connection exists */
            cmd =;    /* Read user comand */
            error = 0;
            switch (cmd) {
                case 'r':
                case 'R':
                    /* Read request - read in temperature and humidity */
                    error += sMeasure ((unsigned char *)&humidVal, MEASURE_HUMI, 0);
                    if (debug) {
                        Serial.print("In main loop: humidVal is ");
                        Serial.print(humidVal, HEX);
                        Serial.print(" and return value is ");
                        Serial.println(error, DEC);
                    error += sMeasure ((unsigned char *)&tempVal, MEASURE_TEMP, 0);
                    if (debug) {
                        Serial.print("In main loop: tempVal is ");
                        Serial.print(tempVal, HEX);
                        Serial.print(" and return value is ");
                        Serial.println(error, DEC);
                    if (error)
                    else {
                        fHumidity = float(humidVal);
                        fTemperature = float(tempVal);
                        calcTempHumid (&fHumidity, &fTemperature);
                        dewPoint = calcDewPoint (fHumidity, fTemperature);
                        printReading ("Temperature is ", &fTemperature, "\xb0 Celsius");
                        printReading ("Humidity is ", &fHumidity, "%");
                        printReading ("Dew point is ", &dewPoint, "\xb0 Celsius");
                case 'd':            /* "Toggle" debug flag for printing */
                case 'D':            /* intermediate data */
                    debug ^= 1;
                    if (debug)
                        Serial.println("**** Debugging enabled ****");
                        Serial.println("**** Debugging disabled ****");
                case 's':            /* Read status register */
                case 'S':
                    /* Read request - read in temperature and humidity */
                    error += sMeasure ((unsigned char *)&statusVal, STATUS_REG_R, 1);
                    Serial.print("Status register contains 0x");
                    Serial.println(statusVal, HEX);
                    Serial.println("Unrecognized command.");
    void toggleAlertLed(){
      if (alert && alertledstate == HIGH)
        alertledstate = LOW;
        alertledstate = HIGH;
    void toggleOkLed(){
      if (okledstate == HIGH) 
        okledstate = LOW;
        okledstate = HIGH;
    void greeting(){
      /* interface led greeting */
      pinMode(OKLED, OUTPUT);
      delay(250);                /* green show */
      pinMode(ALERTLED, OUTPUT);
      delay(250);                /* red show */
      delay(500);                /* amber show */
                                 /* set green */
    void setup()
      okcnt = OKBLINK;
      alertcnt = ALERTBLINK;
      okledstate = LOW;           /* led is on when state is LOW */
      alertledstate = HIGH;       /* led is off when state is high */
      Serial.begin(9600);         /* Open Arduino serial communications */
      pinMode (CLOCK, OUTPUT);    /* set pins for SHT-11 */
      pinMode (DATA, OUTPUT);     /* set pins for SHT-11 */
      sConnectionReset ();        /* Reset the SHT11 device */
      Ethernet.begin(mac, ip);    
      greeting();                 /* flash led interface */
    void loop()
      char cmd;                   /* command input by user */
      int humidVal;               /* humidity value read from SHT1x */
      int tempVal;                /* temperature value from SHT1x */
      unsigned char statusVal;    /* contents of status register */
      float fHumidity;            /* working value for humidity calculation */
      float fTemperature;         /* working value for temperature calculation */
      float dewPoint;             /* calculated Dew Point value */
      unsigned char error;        /* return value for routine calls */
      int num;
      char str[10];  
      Client client = server.available();
      if (client) {
        // an http request ends with a blank line
        boolean current_line_is_blank = true;
        while (client.connected()) {
          if (client.available()) {
            char c =;
            // if we've gotten to the end of the line (received a newline
            // character) and the line is blank, the http request has ended,
            // so we can send a reply
            if (c == '\n' && current_line_is_blank) {
              // send a standard http response header
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: text/html");
              Serial.println("Serving page.");

    TomWare tombox v1 (oct 2010)

    "); client.println("Arduino sensing and monitoring box "); client.println(" "); client.println("digital pin 2,3: bicolor Led red/green cathodes "); client.println("digital pin 4: reed magnetic sensor "); client.println("digital pins 5,6: clk,data of SHT-11 temp and humidity sensor "); client.println("Analog pin 0: smoke sensor "); client.println("
    "); client.println("The 0-5 (6) analog (0-1023) lines "); for (i = 0; i < 6; i++) { client.print("analog input "); client.print(i); client.print(" is "); client.print(analogRead(i)); client.println(" "); } client.println("
    "); client.println("The 2-4 digital (0-1) lines "); for (i = 2; i < 5; i++) { client.print("digital input "); client.print(i); client.print(" is "); client.print(digitalRead(i)); client.println(" "); } client.println("The 7-9 digital (0-1) lines "); for (i = 7; i < 10; i++) { client.print("digital input "); client.print(i); client.print(" is "); client.print(digitalRead(i)); client.println(" "); } client.println("
    "); // ---------Temp & Humid readings ------------------------------ error = 0; error += sMeasure ((unsigned char *)&humidVal, MEASURE_HUMI, 0); error += sMeasure ((unsigned char *)&tempVal, MEASURE_TEMP, 0); if (error) { client.println(" SHT11 error, resetting... "); sConnectionReset(); } else { fHumidity = float(humidVal); fTemperature = float(tempVal); calcTempHumid (&fHumidity, &fTemperature); dewPoint = calcDewPoint (fHumidity, fTemperature); client.print("Temperature: "); splitFloat (&fTemperature, &num, str, 1); client.print(num, DEC); client.print("."); client.print(str); client.println("\xb0 Celsius"); client.println(" "); /* temperature alert threshold */ if (num > 30) { Serial.println("temp threshold exceeded."); alert = true; } else { alert = false; } /* --------------------------- */ client.print("Humidity: "); splitFloat (&fHumidity, &num, str, 1); client.print(num, DEC); client.print("."); client.print(str); client.println("%"); client.println(" "); client.print("Dew point: "); splitFloat (&dewPoint, &num, str, 1); client.print(num, DEC); client.print("."); client.print(str); client.println("\xb0 Celsius"); client.println(" "); } /* Notify on green led that page serving is in progress inverting its state */ toggleOkLed(); pinMode(OKLED, OUTPUT); digitalWrite(OKLED,okledstate); /* client.println("
    The 2-4 (3) briefly output digital (0-1) lines "); for (int i = 2; i < 5; i++) { pinMode(i, OUTPUT); digitalWrite(i,LOW); delay(10); pinMode(i, INPUT); delay(10); } */ break; } if (c == '\n') { // we're starting a new line current_line_is_blank = true; } else if (c != '\r') { // we've gotten a character on the current line current_line_is_blank = false; } } } // give the web browser time to receive the data delay(1); client.stop(); } // --------- Led Blinking ------------------------------ okcnt--; if (okcnt < 1) { okcnt = OKBLINK; toggleOkLed(); pinMode(OKLED, OUTPUT); digitalWrite(OKLED,okledstate); } alertcnt--; if (alertcnt < 1) { alertcnt = ALERTBLINK; toggleAlertLed(); pinMode(ALERTLED, OUTPUT); digitalWrite(ALERTLED,alertledstate); } // --------- Led Blinking end ------------------------------ }

    Marco ( @mgua on twitter)