My Pi Description

My Experiences With the Raspberry Pi -- Tracking My Learning -- My Pi Projects

Monday, April 20, 2015

Serial Transmission - Gertboard (Like an Arduino) to Raspberry Pi

Introduction

If you read my post of March 14, you know I have an enclosure with temperature sensors, and a Raspberry Pi with a Gertboard attached that connects to a receiver board. The enclosure transmits sensor data to the receiver board. The receiver passes the decoded data to the ATmega328P microcontroller on the Gertboard. I covered the transmission, via 434 MHz transmitter and receiver in my March 14 post. Check it out here.
The last piece of the data chain is to pass the data to the Raspberry Pi. A python program, running on the Raspberry Pi, is in charge of obtaining the measurements from the C++ program running on the Gertboard's ATmega328P. As long as the sensor enclosure is transmitting, the Gertboard receives the measurements.
If you wonder why I pass data to the Raspberry Pi it is because I can get graphs like this:
I can get a log file like this (just the beginning of the file):
I can setup the measurement run with this graphical user interface I created:

Data Captured By the Receiver

ROM codes, and 12 bytes of description for each DS18B20 sensor, are stored in the EEPROM of the enclosure's ATMega328P. One temperature sensor is permanently connected to the enclosure, but I can connect as many other sensors as I wish. However, the ROM codes and descriptions for those other sensors must be stored in the EEPROM. When I apply power to the enclosure, we find out what sensors are attached by attempting to read from the scratchpad of each sensor for which we have a ROM code. If the CRC passes, we know the sensor is connected.
I have a full suite of ATmega328P, C++ sketches, for adding, editing, and removing sensor data from the EEPROM. Check it out here. I also wrote my own library for the DS18B20 temperature sensor, and other libraries. Check out my libraries here.
Let's assume I have data for five sensors stored in the EEPROM and sensor's 1, 3, and 5 are connected to the enclosure. I command each sensor, in turn, to make a temperature measurement. When the measurement is available, we assemble 20 bytes of data (data for one sensor). The first byte is always the number of sensors that are connected to the enclosure. For our example, that number is 3. The next to the last byte is the number of the sensor which corresponds to its position in the EEPROM. In our example, that will be 1, 3, or 5. The other bytes correspond to the temperature measurement, high and low alarm temperature, and the sensor description. The last byte is the CRC. We continually make measurements running through each of the connected sensors.
The receiver, continually, looks for valid data. If it recognizes synchronization pulses (see my March 14 post), it sees that the data is valid. It decodes the 20 bytes of Manchester encoded data for the sensor that happened to be transmitting. It may be sensor 1, 3, or 5. It looks at the first byte of data to find the number of sensors in the measurement run. In this case it will be three. An array is initialized whose length is the number of sensors, three in our case, times the number of data bytes per measurement, which is 20. In our example, the array will be 60 bytes long. The data for the first sensor is placed in the array. Next, the receiver code looks for, and captures, data for the next two measurements. This data is appended to the array. Now we have 60 bytes of data. The order of the data may be for sensors 1, 3, and 5; or 3, 5, and 1; or 5, 1, and 3.
After accumulating the 60 bytes, the receiver code looks to see if the Raspberry Pi's python program is requesting the data. If not, the data in the array is overwritten with the next series of measurements. There will be a minimum of one minute between requests from the Pi to the receiver (selected by the user). Depending upon the resolution of the sensor and how power is applied to the sensor (normal or parasitic) the receiver will have those 60 bytes available about every 300ms. to every 2200ms. Therefore, you can see that most of the measurements are lost.

Receiver Code

I have taken another fragment of the C++ code running on the Gertboard's ATmega328P. Visit here to see the entire script.
/*--------------------- This is a program fragment from:
https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Gertboard%20Arduino%20Sketches/Temp_RF_toPython_MultipleSensors_VER2.ino#L25
-----------------
*/
/*-------------------------------Global Variables-------------------------------*/
const int frame_len = 20;
byte frame[frame_len]; // Data for one sensor from transmitting device
/*-------------------------------transmit_data()-------------------------------*/
void transmit_data(char xmit_data[], int xmit_length){
char buff[2];
if (Serial.available()){ //check to see if python put start character on serial port
Serial.readBytes(buff, 1); //get character from serial port.
if (buff[0] == 's'){ // s for start
for (int i = 0; i < xmit_length; i++){
Serial.print(xmit_data[i]);
}
}
}
}
/*_______________________________Main Program____________________________________*/
/*-----------------------------------setup()-------------------------------------*/
void setup() {
Serial.begin(115200);
}
/*------------------------------------loop()------------------------------------*/
void loop() {
boolean CRCs_good;
int i, j;
int number_of_sensors;
CRCs_good = true;
//Get one frame and find out how many sensors and put the first sensor in xmit_data
synchronize(); //find synchronization
manchester_data(); //find one frame worth of data, get frame[]
if (!calculateCRC_byte(frame, frame_len)){
number_of_sensors = frame[0];
char xmit_data[number_of_sensors * frame_len]; //define xmit_data here
for (j = 0; j < frame_len; j++){
xmit_data[j] = frame[j];
}
//this will add the rest of the sensors
for (i = 1; i < number_of_sensors; i++){
synchronize(); //find synchronization
manchester_data(); //find one frame worth of data, get frame[]
if (calculateCRC_byte(frame, frame_len)){
CRCs_good = false;
}
else{
for (j = 0; j < frame_len; j++){
xmit_data[frame_len * i + j] = frame[j];
}
}
}
if (CRCs_good){
transmit_data(xmit_data, frame_len * number_of_sensors);
}
}
delay(100);
}
The code fragment includes the function, "transmit_data()" that looks for a request from the Pi and transfers the data to the Pi. I also included some of the code in "loop()" to illustrate the sequence of events.
To initiate a data transfer cycle, we first look for synchronizing pulses by running line 41 (see blog post of March 14 for this function). We stay here until we find valid synchronization. Once synchronization is confirmed, we move to line 42, the "manchester_data()" function. This will return data for one sensor - the sensor that was transmitting at the time. The code for the "manchester_data()" function can also be found at my March 14 post. If the CRC passes, we now read the first byte of the data to see how many sensors are connected to the enclosure. Now, that we know how many sensors, we can declare the array "xmit_data[]". This array will hold all of the data for all of the sensors for one measurement cycle. After populating "xmit_data[]" with the data from the one sensor we have acquired, we repeat "synchronize()" and "manchester_data()" for each of the other sensors in the run. Now, we have all of the data. Next is to see if the Raspberry Pi has called for the data.
We are now down at line 68 assuming there were no CRC errors. Line 68 takes us to the function "transmit_data()". The function looks to see if there is anything on the ATmega's serial bus (line 15). If so, it is read and put into the array "buff[]" by implementing "Serial.readBytes()". We are looking for one character, and that character is "s". If we find the "s", we place all the data, one byte at a time, onto the serial bus (via the print statement in line 19). If there was no request from the Pi for data, the contents of "xmit_data[]" will be overwritten with new data.

Python Code Running In the Raspberry Pi

The following is a fragment from a rather long program running on the Pi. The program handles setting up the log files for storing the data, sets up the graph parameters, obtains sensor information (description, high and low alarm settings, and resolution), calls the GUI program and incorporates the user responses, makes and records the temperatures, and creates the graphs. The entire program is here. This program calls another python program that handles the graphical user interface. That program is here.
---This is a program fragment. The entire program can be seen at: https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Python%20Programs%20Running%20On%20The%20Pi/GraphRemoteTemperature_V1R3.py---
import serial
ser = serial.Serial('/dev/ttyAMA0', 115200, timeout = 5)
frame_length = 20 # One frame is all the data for one device.
global start_time
def retrieve_serial():
"""
Called by number_of_sensors()
First we flush anything that might be on the serial port
We write the character "s" to the serial port.
The Gertboard checks to see if this character is present
If so it will write the last series of measurements to the serial port
This function reads the data on the serial port every second
until it finds the number of bytes to match a multiple of the
number of bytes for each device.
If the serial data is not found in 10 seconds, the function exits
Returns the length of the message it has received.
"""
ser.flushInput() # Make sure no lingering bytes on serial port
ser.write("s") # send "s" to trigger Gertboard to transmit data
start_time = time.time()
while time.time() - start_time < 10:
time.sleep(1)
recv_length = ser.inWaiting() # finds how many bytes on serial port
if recv_length > 0 and recv_length % frame_length == 0:
return recv_length # good result
return 0 # failure
def number_of_sensors():
"""
Called from get_stored_data() and get_measurements()
This calls retrieve_serial()
retrieve_serial() returns the length of the receive data
This function calculates the number of sensors from the
received data and populates recv_data[] with all the
data retrieved from the Gertboard.
Returns the number of sensors
"""
global recv_data
recv_data = [] # Where Gertboard data will go
sensors = 0
recv_length = retrieve_serial() # will be 0 if failed
if recv_length:
sensors = recv_length / frame_length
in_coming = ser.read(size = recv_length) # get the serial data here
for i in range(recv_length):
recv_data.append(ord(in_coming[i]))
return sensors
view raw gistfile1.py hosted with ❤ by GitHub
The function "number_of_sensors()" is called once to obtain the sensor information: description, alarms, and resolution. Then, it is called every time the program calls for temperature measurements. When the function exists, if there was valid data, all of the data from all of the sensors will be in the global array "recv_data[]". In addition, the function returns the number of sensors in the run.
"number_of_sensors()" calls the function "retrieve_serial()". "retrieve_serial()" does the actual work of requesting data from the ATmega328P on the Gertboard, and retrieving the response from the Gertboard. When requested by "number_of_sensors()", it clears the serial port of lingering data, writes the character "s" to the serial port, and waits for a response from the Gertboard. It will check every second for data. If it sees no data, or if the length of the data does not equal a multiple of 20 bytes, it keeps looking. If it has not found valid data after 10 seconds, it gives up and returns "0". If valid data is seen, it returns the number of bytes received.

Saturday, April 11, 2015

Printing Leading Characters With Arduino IDE Serial Monitor

I have a blog post on calculating and checking the Cyclic Redundancy Check (CRC) byte when transmitting serial data. Here is a link. Near the bottom, is a sketch fragment of my CRC function and a table. The table illustrates how the CRC is calculated as the function progresses, bit, by bit, through the data. Here is the output I received from the Arduino IDE Serial Monitor:
That's really ugly. The serial monitor that is part of the Arduino IDE does not print leading zeros. I wanted to see those zeros. "CRC" is an integer, so has 16 bits. "inByte[i]" is 8 bits long. I wrote a small function to calculate how many leading zeros to print when printing a binary number. Then, I expanded it to to handle numbers of any base, and finally, to add any leading character, not only zeros. This is the output using my leading character function:
My leading character function follows. It is amazingly simple. However, it's not universal. It does not handle minus signs or decimal points:
void printleading(long to_print, int positions, int base, char chtr){
double factor = pow(base, (positions -1));
while ((to_print < factor) && (factor >= 1)){
Serial.print(chtr);
factor /= base;
}
}
The "pow" operator raises the value in "base" to the power of "position" - 1. For example, if you wish to print a 16 bit binary number, "factor" will be 215. You can see that "factor" can become a very large number, especially if you are dealing with decimal or hex numbers. Consequently, "factor" is a double, a floating point data type. However, the function may not work if "factor" wants to be too large. Just imagine if you wanted 16 characters of a decimal number. "factor" will be 1,000,000,000,000,000. A double data type for all Arduinos beside the Due is four bytes in length, not enough bytes to express 1015. The Due may be able to handle 1015 - it's double is 8 bytes in length.
Leading spaces can come in handy for printing dates. You can use it to line up dates like this:
  • April   9, 2015
  • April 10, 2015

Saturday, March 14, 2015

Manchester Encoding/Decoding Data Between Devices

My most recent posts have been about making temperature measurements with the Maxim/Dallas DS18B20 temperature sensors. I have an enclosure with a 2 line by 16 character display that can connect to many of these sensors.
If I want to go beyond merely displaying the temperature, and wish to record and graph the temperature, I wirelessly transmit the data from the enclosure to my Raspberry Pi. Consequently, I need some sort of transmitter and receiver. The transmitter and receiver I chose operate at 434MHz and are small and simple. Both are available from Sparkfun Electronics.
I don't transmit directly to the Pi because I want the receiving device to be dedicated to processing the received data, A microcontroller is ideal for that type of task. A multitasking microprocessor, like the Pi, cannot do this very well - it doesn't focus on one task. The Pi, however, is really good at logging and storing data. My Pi has a marvelous capability to graph temperatures (See my posts about RRDTool).
My receiver connects to my Gertboard, which, in turn, connects to my Pi. The Gertboard has the same microcontroller device as an Arduino Uno: an Atmel ATmega328P. My temperature measuring enclosure also has the same microcontroller.
My next post will tell how my data gets from the Gertboard to the Raspberry Pi. It's an interesting story and deserves a post of its own.

Asynchronous Data Transfer

I am sending data asynchronously, it can start at any time. The receiver must be able to find the start of a burst of data. For that to happen, I precede the data with a synchronization pattern. This pattern is chosen so that it can never be confused with the actual data. I accomplish this by encoding the actual data in a way that there are never more than two logic 1's or two logic 0's together. My synchronization pattern, then, must have more than two 1's and/or two 0's, together.
I use Manchester encoding with my data, which is a standard protocol. Every logic 1 in the data is replaced with a 01, while a logic 0 becomes a 10. You can see how this avoids more than two 0's or 1's together. For example: 0000 becomes 10101010. Only where there is a change in logic level will you find two 0's or 1's together. For example: 001100 becomes 101001011010.
There is a good reason for avoiding long strings of 1's or 0's: the receiver will see this an an interruption of data. The receiver has an automatic gain control, and if it sees no data, it will increase its gain to the maximum. The receiver will then output rail to rail thermal noise (See the beginning of the yellow scope trace below).
The disadvantage of this scheme is that I must transmit two bits for every single bit of data.
Here is what the start of my data looks like on the scope:
The upper trace (red) is the data to the transmitter, while the lower trace (yellow) is the received data at the Gertboard.
After every burst of transmitted data, there is a lapse of several hundred milliseconds (transmitter outputs 0V). During this time one if the temperature sensors makes its measurement and converts the measurement to two bytes of digital data. At some point during this dead time, the receiver's automatic gain control goes to its maximum. You can see the resulting noise in the beginning of the trace of the receiver's output.
You can clearly see the two synchronization pulses in both the transmitted and received data. The synchronization pulses consist of four high bits followed by four low bits. The synchronization pulses are preceded by a 101010 pattern. The receiver will recognize this pattern as actual data and will adjust its automatic gain control. There is 10 pattern following the synchronization pulses. The start of the Manchester encoded data follows that.

My Data

I am sending 20 bytes of data with each measurement:
  • byte 0: Number of sensors being accessed
  • byte 1 and 2: From the DS18B20 Scrathpad - the measured temperature
  • byte 3: From the DS18B20 Scrathpad - Upper temperature alarm. Previously set by the user
  • byte 4: From the DS18B20 Scrathpad - Lower temperature alarm. Previously set by the user
  • byte 5: From the DS18B20 Scrathpad - Resolution (9, 10, 11, or 12 bits). Previously set by the user
  • byte 6 through 17: From the ATmeta328P EEPROM - Sensor Description. Previously set by the user
  • byte 18: The number of the sensor as determined by its position in the ATmega328P's EEPROM.
  • byte 19: Cyclic Redundancy Check (CRC) byte calculated from the previous 19 bytes.
Except for byte 0, each burst of data contains the data from one temperature sensor. Each sensor is accessed, in turn, before starting with the first sensor, again.

Transmit Code

The following is a fragment of the code I usually run on my Temperature Sensor Enclosure. I say usually because I can upload other code to the box via its attached USB/FTDI port. The entire code can be seen here:
The enclosure has one permanently mounted DS18B20 temperature sensor and three receptacles for plugging in more sensors. It is possible to connect hundreds of these sensors to the enclosure (normal and parasitic power is supported). However, I only have room in the ATmega's EEPROM for the ROM codes and descriptions of 50 sensors. In the photo above, you can see I have two DS18B20 cables attached to the box. The code auto-detects the sensors when the code starts. As long as the ROM code and description of the sensor is in the EEPROM, the code will include the sensor in the measurements and in the transmitted data. If I have a new sensor, I have code to upload to the enclosure that will detect new sensors and will prompt for description, and alarm and resolution settings.
-----This is a program fragment from:
https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/RF%20Transceiver/Xmit2PiWithLCD_AutoSelect/Xmit2PiWithLCD_AutoSelect.ino
-----
/*-------------------------------------------------------------------------------------------------*/
#include <avr/io.h>
/*---------------------------------------------Global Variables-------------------------------------*/
byte rom[8];
byte scratchpad[9];
const int bit_time = 833; //833 usec. - 1200baud
int description[12];
int number_of_devices_to_run;
boolean parasitic = false;
int stored_devices;
boolean devices2run[50];
byte xmit_data[20];
char disp_temp[9];
int device_displayed = 1;
//Output to 454MHz Transmitter Is On PB4
#define PORT_1 PORTB
#define PORT_PIN_1 4
#define DDR_1 DDRB
//Switch is on PB2
#define PORT_2 PORTB
#define PORT_PIN_2 2
#define DDR_2 DDRB
#define PIN_2 PINB
#define DATAMASK_2 0b00000100
/*---------------------------------------------synchronize-------------------------------------*/
void synchronize(){
// send 101010 as beginning pattern
for (int i = 0; i < 3; i++){
PORT_1 |= (1 << PORT_PIN_1);
delayMicroseconds (bit_time);
PORT_1 &= ~(1 << PORT_PIN_1);
delayMicroseconds (bit_time);
}
// send 11110000 as sync pattern
PORT_1 |= (1 << PORT_PIN_1);
delayMicroseconds(bit_time * 4);
PORT_1 &= ~(1 << PORT_PIN_1);
delayMicroseconds(bit_time * 4);
// send 10
PORT_1 |= (1 << PORT_PIN_1);
delayMicroseconds (bit_time);
PORT_1 &= ~(1 << PORT_PIN_1);
delayMicroseconds (bit_time);
}
/*---------------------------------------------send_data-------------------------------------*/
void send_data(byte xmit_byte){
for (int i = 0; i < 8; i++){
// Data transmitted using Manchester Encoding
// we start with MSB first
// each raw bit becomes two transmitted bits.
// a 1 becomes a 01, a 0 becomes a 10
if (xmit_byte > 127){ // true if MSB is a 1
PORT_1 &= ~(1 << PORT_PIN_1); //xmit 0
delayMicroseconds (bit_time);
PORT_1 |= (1 << PORT_PIN_1); //xmit 1
delayMicroseconds (bit_time);
}
else{ // MSB is 0
PORT_1 |= (1 << PORT_PIN_1); //xmit 1
delayMicroseconds (bit_time);
PORT_1 &= ~(1 << PORT_PIN_1); //xmit 0
delayMicroseconds (bit_time);
}
xmit_byte <<= 1; // left shift i position
}
}
Code Fragment of Sketch Running On ATmega328P in Enclosure To Transmit Data to Gertboard.
Whenever we are ready to transmit data, the function "synchronize()" is called, followed by 20 calls to function "send_data()" - one call for each data byte in the burst. The timing is established by the global variable "bit_time". It is calculated to send data at 600 baud (1200 bps - remember it takes 2 Manchester encoded bits to send one bit of data).
Note my use of ATmega register programming rather than "bitMode" and "digitalWrite". I have a whole tutorial about register programming at by blog here:

Receive Code

The following is a fragment of code that runs on my Gertboard that receives Manchester encoded data from my Temperature Sensor Enclosure. The entire code can be found here.
----- This is a code fragment from:
https://github.com/RaspPiGuy/DS18B20TempSensor-Arduino-Pi/blob/master/Gertboard%20Arduino%20Sketches/Temp_RF_toPython_MultipleSensors_VER2.ino#L25
-----
/*------------------------------------------------------------------------------*/
#include <avr/io.h>
/*-------------------------------Global Variables-------------------------------*/
volatile boolean found_transistion;
const int frame_len = 20;
byte frame[frame_len]; // Data for one sensor from transmitting device
const int bit_time = 833; //833 usec. = 1200 baud (600 for data)
#define PIN PIND //Arduino Input is on port D
#define DATAMASK 0x04 //Arduino pin2 or PD2
/*--------------------------Interrupt Service Routine----------------------------*/
ISR(INT0_vect){
found_transistion = true;
}
/*-----------------------------------synchronize()-------------------------------*/
void synchronize(){
// Routine to find synchronization
unsigned long time, duration;
boolean val; // logic level of PD2 pin - Arduino pin 2
boolean sync; // will be true if synchronization has been accomplished
int upper_threshhold = 4 * bit_time + 4 * bit_time / 10; // time of 4 bits + 10%
int lower_threshhold = 4 * bit_time - 4 * bit_time / 10; // time of 4 bits - 10%
sync = false;
do{
found_transistion = false;
time = micros();
while (!found_transistion); // We stay here until interrupt occurs
duration = micros() - time;
val = PIN & DATAMASK;
if (!val){
if ((duration > lower_threshhold) & (duration < upper_threshhold)){ //time of 4 bits +/= 10%
found_transistion = false;
time = micros();
while (!found_transistion);
duration = micros() - time;
val = PIN & DATAMASK;
if (val){
if ((duration > lower_threshhold) & (duration < upper_threshhold)){ //time of 4 bits +/= 10%
sync = true;
}
}
}
}
} while(!sync);
}
/*-------------------------------manchester_data()-------------------------------*/
//after synchrozination, receives one frame from transmitting device
void manchester_data(){
unsigned long time, duration;
int no_bytes, no_clocks;
boolean present_bit; // keeps track of last bit of Manchester encoded data
byte hold_byte = 0; // recovered data flows into this variable
int threshhold = bit_time + bit_time / 2; // bit_time + 50%
// Finding the single positive pulse after synchronization
found_transistion = false;
while (!found_transistion);
// Now we are into the Manchester encoded data
no_bytes = 0;
present_bit = false; // equals 0
do{
no_clocks = 0;
do{
found_transistion = false;
time = micros();
while (!found_transistion); // waiting for interrupt
duration = micros() - time;
if (duration > threshhold){ //found bit change if true
present_bit = !present_bit;
no_clocks += 2; // a bit change will take up two clock pulses
}
else{
no_clocks += 1; // if there was no bit change
}
if (!(no_clocks % 2)){ // we look at every other clock time
hold_byte <<= 1; // last bit is shifted left one position
hold_byte += present_bit; // new bit goes into the LSB position
}
}while (no_clocks < 16); // we have received one byte with 16 clocks
frame[no_bytes] = hold_byte; // transfer that byte to array
no_bytes++;
} while(no_bytes < frame_len); // raw data stream is mess_len bytes long
}
Code Fragment of Sketch Running On ATmega328P on the Gertboard To Receive Data from the Temperature Sensor Enclosure.
While the transmit code is pretty easy to figure out, the receive code is interesting and bears some analysis. First, it illustrates the use of ATmega interrupts. Not shown in the code fragment are two lines in setup():
EICRA = B00000001; // Any change will trigger interrupt
EIMSK = B00000001; // Enable INT0 interrupt
This means that any change in logic level of the ATmeta328P pin connected to the receiver circuitry will trigger an interrupt. Put another way: if the logic level changes from 0 (0V) to 1 (3.3V) or from 1 (3.3V) to 0 (0V), an interrupt is issued.
Lines 18 - 20 constitutes the Interrupt Service Routine. Whenever an interrupt is issued, the variable "found_transistion" becomes true. We set "found_transistion" false, in lines 34, 41, 66, and 75. When the "while" statements in line 35, 43, 67, and 77 are reached, processing is halted until the interrupt occurs. Using the "time" and "duration" variables and the "micro()" function, the time between interrupts (corresponds to the time between transitions) can be determined.

Analyzing The Receive Data

When sychronize() is called from the main program, it looks for a positive pulse of 4 bits in duration (plus or minus 10%). It keeps looking until it find it. If it next finds a negative pulse of 4 bits in duration (plus or minus 10%), it exits the routine. It will stay in this function until it is satisfied it has found the synchronization pattern.
Once we drop out of the sychronize() function, the manchester_data() function is called. We stay in that function until 20 bytes are received. Looking at the waveform above, we start in the function at point "c". Next we look for one more transistion (lines 66 and 67) to bring us to point "d".
We look for the actual received data by entering the outer "do" loop at line 72, performing the inner "do" loop (line 74) 20 times. The logic level of each bit of data we find is tracked by the variable "present_bit". This starts as 0 because the 10 pattern following the synchronization pulses is equivalent to a Manchester code of 0.
We are at point "d" looking for the next transition which occurs at point "e". Using the threshold of 1.5 times the time of one bit (in global variable bit_time), we determine if we have encountered a change in logic level from the original 0 to a 1. Since the time from point "d" to "e" is obviously less than the threshold, we have not encountered a change in logic level. Therefore, the first bit received is a 0. The "if/else" statements in lines 80 to 86 determine the actions taken if we do exceed, or do not exceed the threshold. Since we have not, "present_bit" does not change and the variable "no_clocks" is incremented by 1.
The variable "no_clocks" has two functions. First, it indicates when we have received a bit of data. Since we must receive two bits of Manchester encoded data for each bit of sensor data, we take no action if "no_clocks" is an odd number ("if" statements lines 87 to 90). If "no_clocks" is even, we capture the last bit by shifting the contents of variable "hold_byte" to the left, and inserting the value of "present_bit" at the least significant position of "hold_byte".
The second function of "no_clocks" is to tell us when we have received an entire byte of sensor data. This will be the case if "no_clocks" reaches 16. If that is the case, the value of "hold_byte" is transferred to the next byte of the array "frame[]". When we have received all 20 bytes of "frame[]" we exit the function.
When last we were looking at the waveform, we were at point "e". We return to the beginning of the inner "do" loop to look for the next transition (point "f"). The time from "e" to "f" is also less than the threshold. We return back to the beginning of the inner do loop and find the next transition (point "f" to "g"). This time we find the threshold is exceeded so the value of "present_bit" flips to a 1 and "no_clocks" increments by 2. I think the action is easy to follow from here.

Monday, March 9, 2015

Get Rid of MaAfee On Your Brand New Computer

I just purchased a new Windows laptop. Between all the bloat and the pre-installation of McAfee I was tempted to reformat the hard disk, purchase a copy of Windows 8.1, and start from scratch.
What a racket McAfee has. They give you a free subscription for a couple of months. So what do you do when that expires? I would bet the vast majority of people either do without virus protection, or pay McAfee every year to maintain their protection. Nearly everyone knows the dangers of being unprotected, so I would guess most simply pay McAfee.
I want the free Microsoft Windows Defender as my virus protection. With McAfee present, Defender is turned off. With a little web search, I found it was quite easy to remove McAfee and turn on Defender.
I added one step to the process. I turned off my network connection.
This all applies to a new computer with Windows 8.1. It turned out to be really simple and painless. Here is what I did:
  1. Downloaded the McAfee Consumer Product Removal Tool (MCPR) - main paragraph 2a. from the link I gave you.
  2. Removed computer from my network because next step removes your protection.
  3. Uninstall McAfee - Main paragraph 1. from the link. No problems here.
  4. Find where you stored the MCPR.exe and run it. Just answer the questions asked. The prompt in paragraph 2f. never appeared so I did not have to deal with it.
  5. When you see "CleanUp Successful" reboot your computer.
  6. When you are up and running again connect yourself to your network.
Check the action center (white flag in the notification area of the taskbar). Click on "Open Action Center" and then click on "Security". You will see that your firewall is protected by Windows and your virus and spyware protection is now provided by Windows Defender. You don't have to do anything to turn it on.