Digital logic
Looking at Signals on I2C on WeatherPiArduino
Next month, SwitchDoc Labs is doing an article on WeatherPiArduino, an interface board for both the Raspberry Pi and Arduino to talk to weather instruments, including a new lightning detector. It uses a number of I2C devices, as well as connecting to an anemometer/wind vane and rain bucket. I am currently doing the final testing on this new board and thought I would use the logic analyzer to start looking at the I2C bus (Figure 4).
One of the most powerful features of this logic analyzer is the ability for it to record and then display protocol information. Take a look at the trace in Figure 5. It shows a trace of the I2C bus when the computer is writing to the WeatherPiArduino BMP180 Barometer/Temperature I2C device. The protocol analyzer states that I am writing to I2C address 0x77 (the address for the BMP180), setting up a write to address 0xF4 (Measurement Control), and then writing out the data 0x2E, which sets up the BMP180 to start a temperature measurement.
The trace in Figure 6 shows a read of the DS3231 real-time clock [2] that is also connected to the WeatherPiArduino board. This trace shows a much more complex sequence, all nicely decoded by the logic analyzer. See how hard it would be to read these sequences by hand? This shows first a write to the I2C address 0x68, which is the address for the DS3231, then a command to read out the time from the DS3231 (0x00), and then the read from the DS3231 address 0x68 consisting of seconds, minutes, hours, day, date, month, and year in seven single-byte read transfers.
The trace in Figure 7 is from a SunAir board talking to the MouseAir motor controller board driving a stepper motor in the Sun Tracker system (see the Sun Tracker article elsewhere in this issue). Figure 8 shows the setup.
A stepper motor is a brushless DC electric motor that divides a full rotation into a number of equal steps. The motor's position can then be commanded to move and hold at one of these steps without any feedback sensor (an open-loop controller), as long as the motor is carefully sized to the application.
To make a stepper turn, you send the two coils of the motor specific signals (Figure 9 shows the trace) to attract the gear teeth with an electromagnet. With the right sequence, one coil is turned off and then the second coil is turned on, making the gear rotate slightly to align with the second gear. Repeating this sequence makes the motor move step by step, hence the name. This allows the motor to be turned by a precise angle.
Listing 2 shows the main part of the code generating this trace.
Listing 2
Code Generating Stepper Motor Trace
001 // Stepper Motor Test for Logic Analyzer 002 // SwitchDoc Labs 1/14/2014 003 004 005 #define LEFTSTEP 0 006 #define RIGHTSTEP 1 007 int Motor1A = 8; // GP2 on SunAir 008 int Motor2A = 13; // Servo on SunAir 009 int Motor3A = 12; // Limit0 on SunAir 010 int Motor4A = 11; // Limit1 on SunAir 011 int EN12 =7; // Not on on SunAir / on SunAirPlus 012 int EN34 = 6; // Not on on SunAir / on SunAirPlus 013 014 015 // stepper controls 016 017 void enable_motor() 018 { 019 digitalWrite(EN12, 1); 020 021 digitalWrite(EN34, 1); 022 023 } 024 025 void disable_motor() 026 { 027 digitalWrite(EN12, 0); 028 digitalWrite(EN34, 0); 029 030 031 } 032 void multipleStep(int count, int direction) 033 { 034 035 enable_motor(); 036 int i; 037 Serial.print("multipleStep: Count="); 038 Serial.print(count); 039 Serial.print(" direction = "); 040 if (direction == LEFTSTEP) 041 Serial.println("LEFTSTEP"); 042 else 043 Serial.println("RIGHTSTEP"); 044 045 046 for (i= 0; i < count; i++) 047 { 048 if (direction == LEFTSTEP) 049 forwardStep(); 050 else 051 reverseStep(); 052 053 } 054 disable_motor(); 055 056 } 057 058 059 060 void forwardStep() 061 { 062 float StepDelay = 50; 063 064 // step 1 065 digitalWrite(Motor1A, 1); // coil 1a 066 digitalWrite(Motor3A, 1); // coil 2a 067 digitalWrite(Motor2A, 0); // coil 1b 068 digitalWrite(Motor4A, 0); // coil 2b 069 delay(StepDelay); 070 071 072 // step 2 073 digitalWrite(Motor1A, 0); // coil 1a 074 digitalWrite(Motor3A, 1); // coil 2a 075 digitalWrite(Motor2A, 1); // coil 1b 076 digitalWrite(Motor4A, 0); // coil 2b 077 delay(StepDelay); 078 079 080 081 // step 3 082 digitalWrite(Motor1A, 0); // coil 1a 083 digitalWrite(Motor3A, 0); // coil 2a 084 digitalWrite(Motor2A, 1); // coil 1b 085 digitalWrite(Motor4A, 1); // coil 2b 086 delay(StepDelay); 087 088 // step 4 089 digitalWrite(Motor1A, 1); // coil 1a 090 digitalWrite(Motor3A, 0); // coil 2a 091 digitalWrite(Motor2A, 0); // coil 1b 092 digitalWrite(Motor4A, 1); // coil 2b 093 delay(StepDelay); 094 095 } 096 097 void reverseStep() 098 { 099 100 float StepDelay = 50; 101 // step 4 102 digitalWrite(Motor1A, 1); // coil 1a 103 digitalWrite(Motor3A, 0); // coil 2a 104 digitalWrite(Motor2A, 0); // coil 1b 105 digitalWrite(Motor4A, 1); // coil 2b 106 delay(StepDelay); 107 108 109 // step 3 110 digitalWrite(Motor1A, 0); // coil 1a 111 digitalWrite(Motor3A, 0); // coil 2a 112 digitalWrite(Motor2A, 1); // coil 1b 113 digitalWrite(Motor4A, 1); // coil 2b 114 delay(StepDelay); 115 116 // step 2 117 digitalWrite(Motor1A, 0); // coil 1a 118 digitalWrite(Motor3A, 1); // coil 2a 119 digitalWrite(Motor2A, 1); // coil 1b 120 digitalWrite(Motor4A, 0); // coil 2b 121 delay(StepDelay); 122 123 124 125 126 // step 1 127 digitalWrite(Motor1A, 1); // coil 1a 128 digitalWrite(Motor3A, 1); // coil 2a 129 digitalWrite(Motor2A, 0); // coil 1b 130 digitalWrite(Motor4A, 0); // coil 2b 131 delay(StepDelay); 132 133 134 } 135 136 137 // the setup routine runs once when you press reset: 138 void setup() { 139 // initialize serial communication at 9600 bits per second: 140 Serial.begin(57600); 141 Serial.println(""); 142 Serial.println("----------start of SunAir SunTracker script---------"); 143 Serial.println(""); 144 145 pinMode(Motor1A, OUTPUT); 146 pinMode(Motor2A, OUTPUT); 147 pinMode(Motor3A, OUTPUT); 148 pinMode(Motor4A, OUTPUT); 149 pinMode(EN12, OUTPUT); 150 pinMode(EN34, OUTPUT); 151 152 153 } 154 155 void loop() { 156 157 158 159 multipleStep(5, LEFTSTEP); 160 161 162 delay(100); 163 164 multipleStep(5, RIGHTSTEP); 165 delay(1000); 166 167 }
Question from Readers
Q: What are some good vendors and software for making your own PC boards like the ones by SwitchDoc Labs?
A: I use two vendors for prototype PCBs: TinySine and DFRobot. Both vendors have given excellent service and help (hats off specifically to TinySine!) when things have been difficult. I do all of my PCB design using CadSoft Eagle software. It has a learning curve, but the free version really works very well for small boards and design. There are many great tutorials online for Eagle.
Buy this article as PDF
Pages: 8
(incl. VAT)