VP Process Inc. has released the SDAFE™, a Software Defined Analog Front End module. This small module (1.9" x 0.95") can be set via it's SPI interface to be either 4-20 mA, 1 to 5 VDC, or 0 to 10 VDC input (other ranges available) and is available as an Isolated (2.5KV Isolation) module:
VPE-3001B SDAFE™
or as a Non-Isolated Module:
VPE-3051B SDAFE™
The PI-SPI-DIN Automation Series of products have SDAFE's available as their primary analog inputs, and an expansion module is available to allow for up to 80 SDAFE™ analog channels to be used as one system.
Power:
3.3VDC or 5.0VDC (Raspberry Pi and Arduino Compatible)
SPI:
MISO Data Input, Active High
MOSI Data Output, Active High During Chip Select, Open Collector Output
SCK Clock
/CS Chip Select, Active Low
Speed Up to 100KHz
Input:
Type 1: (Default) 0 - 20 mA 0 - 20000 Units: mA
Type 2: 0 - 20 mA 0 - 10000 %
Type 3: 4 - 20 mA 0 - 10000 %
Type 4: (Default) 0 - 5 VDC 0 - 5000 Units: VDC
Type 5: 0 - 5 VDC 0 - 10000 %
Type 6: 1 - 5 VDC 0 - 10000 %
Type 7: (Default) 0 - 10 VDC 0 - 10000 Units: VDC
Type 8: 0 - 10 VDC 0 - 10000 %
Type 9: 2 - 10 VDC 0 - 10000 %
AD Converter:
Resolution: 15 bits
Conversion:
15 SPS (Samples per Second)
Accuracy:
+/- .005 reading for mA and VDC Types 1, 4 and 7
+/- .01 reading for mA and VDC Types 2, 3, 5, 6, 8 and 9
Over Range:
Inputs have up to 25% Over Range per input type
Error Status:
Status Register: Over Range Detection when input greater than 125%
Reverse Polarity Detection
Indicators:
Blue LED: Power ON
Green LED: ON When Chip Select Active (Low)
Connections:
J2 Non-Isolated Side
Pin 1: +V (+3.3VDC or +5VDC)
Pin 2: 0V (Common)
Pin 3: MOSI
Pin 4: CLK
Pin 5: /SS (Chip Select)
Pin 6: MISO
Pin 7: no connection (Reserved for HART Module)
Pin 8: no connection (Reserved for HART Module)
Pin 9: no connection (Reserved for HART Module)
Pin 10: no connection (Reserved for HART Module)
J1 Isolated Side (Non-Isolated Side for VPE-3051A)
Pin 1: no connection
Pin 2: no connection
Pin 3: Common
Pin 4: Common
Pin 5: Signal Input mA or VDC
Pin 6: Signal Input mA or VDC
Pin 7: Common
Pin 8: Common
Dimensions:
1.95" x 0.95"
Headers on standard 0.1" spacing
This LCD has a Modbus RTU RS485 interface, is fully programmable (there are 3 pushbuttons on the controller pcb - UP, DOWN and ENTER), has dual wiring ports for easy wiring, and operates from 9 to 24 VDC!
Another feature is the pcb mounted temperature sensor that can be read via the Modbus functions and also displayed on the LCD itself.
The interface shown above uses the Raspberry Pi 3 with the PI-SPI-DIN-RTC-RS485 interface module. The display, being RS485, can be up to 4000 feet away from RPi interface. As shown above, the wiring is a standard Cat5e cable which carries power and the RS485 signals.
Here is the controller module:
The power input is a wide 9 to 24 VDC and can be applied via the RJ45 jacks, the barrel plugs, or the terminal block.
Programming is as simple as pressing the 3 pushbuttons together and following the instructions. For added security, there is a programmable password (4 digit PIN).
All mounting hardware (6-32 screws and spacers) are included int the package.
Here is another picture of the connections to the RPi:
For more information and specs, please visit the product page:
]]>
The user interface module has a 1.4" LCD, three pushbuttons (UP, DOWN, ENTER) and a bi-color (Red/Green/Amber) LED for status indication.
To operate off the RPi 3, the display interface is resource heavy: it uses a total of 19 GPIO lines!
The test software is written in "C" using the Geany compiler. The software features:
The hardware used is the RPI 3, the Pi-SPi-PROTO prototype pcb, and the WL-ERC12864 KIT. The only other components added are three 10K ohm pullup resistors for the push button lines.
In development is a add on module to the Pi-SPi line that uses GPIO expanders to minimize the number of GPIO lines required - the new module will use the SPI bus and 2 chip selects. This design will be more practical for real world applications.
The sample code for the above is available to anyone interested, just drop us a line at info@widgetlords.com.
]]>
This system worked right out of the box with simple programming using the Digi XCTU program.
The RPi 3 was configured for Modbus RTU protocol and using the new RPI3 wireless hat by VP Process Inc.
The analog 8 channel 4-20 mA input module is connected to the RS485 to wireless converter, which is also available in a DIN rail enclosure.
The typical application for this would be where the data acquisition (or control) are located some distance from the controller, in this case the Raspberry Pi. Using the 900 MHz modules proved to be very easy to use, and the distance (indoor range about 2000 square feet) had no effect - everything just worked!
Some things to be aware of for the application programming:
Think in terms of $$ per foot for conduit in an industrial application versus the cost of some simple interfaces and a couple of radio modules. Depending on the distance of the "wire replacement", the savings can be quite significant!
More information on these modules can be found here:
]]>
The Raspberry Pi wireless shield will operate with either the 2.4 GHz Zigbee modules or the 900 MHz Series S3B modules.
The wireless 5 point temperature sensor uses 10K thermistors, and uses the same circuitry covered in a previous blog post found here. The first temperature sensor is located on the PCB itself, and the other 4 temperature sensors can be located up to 10 feet away from the PCB.
The design is based on a PIC18LF14K22 processor, and all of our PIC based designs provide the ICSP programming port. That way, every unit can be used as a development platform when coupled with the Microchip PicKit3 programmer/debugegr tool.
Here is a picture of the reverse side of the PCB:
The design uses our battery power circuit and we expect to get up to 1 year of battery life using standard Alkaline AA batteries. The program transmits the temperature on a programmable "Pulse" time, Alarm Threshold crossing, or a programmable "Delta" temperature. This allows for a relaxed "Pulse" of 4 hours and yet capture all important temperature events.
Once the test programming is complete for the RPi 3 itself, we have a new wireless shield in the design stages and the package should be released by mid June.
Sign up for our news letter if you would like to receive more information on these developments.
Thanks!
]]>
Typically data centers have large breaker panels (up to 42, 60, 72 breakers per panel) and use "CT strips" where the current transformers are on a strip in front of the breakers. Each phase power wire goes through the current transformer before it is attached to the breaker. These types of installations are done during the build stage and before main power is applied.
The circuit shown above is used with current transformers that are a "Split Core" type and can be attached to existing power installations.This type of input circuit is ideal for commercial applications such as mechanical rooms in strip malls, etc.
The design is based on a PIC18F46K80 microprocessor with 12 bit A/D resolution.
Here is the design criteria for the above circuit:
There are other features like dipswitch selection for Modbus ID, lots of LED indicators, baud rate selection via jumper, simple calibration via jumper, plus others.
This design features what can be done with an inexpensive micro like the PIC18F series.
]]>
The devices used in this example are:
For the test software, the RPi is sending relay info as Modbus RTU to the Zigbee module attached via the shield. The zigbee module transmits to the receiver Zigbee module attached to the wireless to RS485 converter module, which in turn communicates with the relay module.
When using this kind of setup, here are a few things to watch out for:
The Wireless to RS485 converter module uses an automatic switch to detect when in transmit mode to switch the RS485 driver IC from Receive to Transmit. This circuit is based on a 555 timer chip, and has reliable operation at 9600 and 19200 Baud.
Distance between the Zigbee modules depends on the type of application (outdoor vs indoor) and the series of modules used - regular Series 2 or the PRO version.
We will be doing some testing with the 900 MHz version of these modules (PRO S3B) in the near future and will post the results as soon as we have them!
]]>
The module uses a dual 12 bit DAC, the MCP4922. Each mA output has a mirror VDC output. The output circuit requires an external supply voltage, I am using a wall adapter style 24 VDC power supply. Each output has a signal strength LED, in this example mA Output 1 is set to 4 mA and mA Output 2 is set to 20 mA.
Schematics can be found on the product page Pi-SPI-2AO link.
The outputs are very easily defined as follows:
Reference Vref = 3.3. The mA circuit is optimized to give 20 mA at a 3VDC output from the DAC. Therefore, 20 mA = 3/3.3 * 4096 DA Counts = 3723 DA Counts.
Here is a very simple test routine written in C (using the Geany compiler on the RPi 3)
/*
* pispi_2ao.c
*
* Copyright 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <math.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
// Define Pins
#define PIN_EN_DA 22
// Prototypes
void Initialize_Pi_Hardware(void);
void Update_Analog_Output(unsigned int dac1, unsigned int dac2);
// Variables
unsigned int DAC1_Counts;
unsigned int DAC2_Counts;
// main
int main(void) {
wiringPiSetupGpio();
Initialize_Pi_Hardware();
digitalWrite(PIN_EN_DA, HIGH);
while(1)
{
// DAC1_Counts = 0; // 0 = 0 mA
DAC1_Counts = 745; // 745 = 4 mA
DAC2_Counts = 3723; // 3VDC/3.3Vref * 4096 = 3723 = 20 mA
printf("DAC1 AD Counts Output = %d \n", DAC1_Counts);
printf("DAC2 AD Counts Output = %d \n\n", DAC2_Counts);
Update_Analog_Output(DAC1_Counts, DAC2_Counts);
delay(500);
}
return 0;
}
void Update_Analog_Output(unsigned int dac1, unsigned int dac2) {
unsigned int output;
unsigned char buf[2];
wiringPiSPISetup(1, 100000);
// Output DAC 1
output = 0x3000;
output |= dac1;
buf[0] = (output >> 8) & 0xff;
buf[1] = output & 0xff;
digitalWrite(PIN_EN_DA, LOW);
wiringPiSPIDataRW(1,buf,2);
digitalWrite(PIN_EN_DA, HIGH);
delay(500);
// Output DAC 2
output = 0xb000;
output |= dac2;
buf[0] = (output >> 8) & 0xff;
buf[1] = output & 0xff;
digitalWrite(PIN_EN_DA, LOW);
wiringPiSPIDataRW(1,buf,2);
digitalWrite(PIN_EN_DA, HIGH);
}
void Initialize_Pi_Hardware(void) {
// SPI CS Enable Lines
pinMode(PIN_EN_DA, OUTPUT);
}
]]>
This system detects water leaks, measures temperatures for the Cold Water Line and Hot Water Lines, drives an audible alarm, and has a test button. Sample code in C using the Geany Compiler also provided.
Parts:
Basic Operation:
The key to this circuit (other than the RPi of course ;), is the versatile analog input circuit of the Pi-SPi-8AI. There are 8 channels using the MCP3208, each channel can be configured as a mA input, a Voltage Input, a Thermistor input, a SPST Switch input, and I modified one channel for a water leak sensor input.
Basic Circuit:
4-20 mA and VDC Input Circuit
The mA input is converted to a voltage across Rload. 20mA x 150 Ohms = 3.0 VDC
For DC Voltge inputs, the Rload resistor is removed. For voltages greater than 3.3 VDC, C2 can be replaced with a resistor creating a voltage divider between R2 and the R where C2 is.
Thermistor Input Circuit
Switch Input
The SPST switch shorts out the input, the ADC sees either full AD counts or close to 0 AD counts
Water Leak Detection Circuit:
Project Setup:
Pi-SPi-8AI
P-SPi-8KO
Here is the test setup before installation:
Here is a screen shot before installation:
How the Water Leak Detector Works:
The K3 output is turned on to provide a 3.3 VDC output to one of the water leak sensor terminals. After a small delay, the Channel 5 is read by the MCP3208. If there are AD counts higher than the threshold setting, then there is a water leak.
This circuit acts as a water conductivity detector, by adjusting the settings, turn on times, etc., this concept can be used for water solids content measuring, soil humidity content, etc.
The reason for toggling the power on the sense circuit is to prevent electrolysis and corrosion on the sensing elements.
Installation:
Here is my brand new water hot water tank!
A close up of the water leak sensor:
And the temperature sensor taped to the hot water line (top to the left) and cold water line (top to the right).
A screenshot of the Pi system in operation:
This is a very basic setup. The next steps are to add email alerts, a nice GUI interface, more detection points, maybe a water shut-off valve, etc.
Detailed specs on the Pi-SPi's can be found here:
Finally, here is the sample code used in the above project:
/*
* pispi_hwt.c
*
* Copyright 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <math.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
// Define Pins
#define PIN_EN_AD 7
#define PIN_EN_K 8
#define OFF 0
#define ON 1
#define WATER_LEAK_THRESHOLD 1000
#define K1 0x01
#define K2 0x02
#define K3 0x04
// Steinhar-Hart Equation Defines for 10K Thermistor Beta 3380 Temp Sensor
#define R_LOAD 10000.0
#define R_ROOM_TEMP 10000.0 // for 25 Deg C
#define T_BETA 3380
#define T_AD_COUNTS 4095 // MCP3208 is 12 bit ADC
#define ROOM_TEMP_NOM 25.0
// Prototypes
void Initialize_Pi_Hardware(void);
void Update_Switch(void);
void Update_Water_Leak(void);
void Update_Temperatures(void);
void Update_Relays(unsigned char status);
void Update_Analog(unsigned char channel);
// Variables
unsigned AN_AD[8];
float Temp_Hot_Line, Temp_Cold_Line;
int Switch;
unsigned char Relay_Status;
unsigned char Water_Leak;
// main
int main(void) {
wiringPiSetupGpio();
Initialize_Pi_Hardware();
digitalWrite(PIN_EN_K, HIGH);
digitalWrite(PIN_EN_AD, HIGH);
Relay_Status = 0;
Switch = OFF;
Water_Leak = OFF;
while(1)
{
printf("Water Leak = %s \n", Water_Leak ? "ON" : "OFF");
printf("Test Switch = %s \n", Switch ? "ON" : "OFF");
printf("Cold Water Line = %0.1f Deg C \n", Temp_Cold_Line);
printf("Hot Water Line = %0.1f Deg C \n", Temp_Hot_Line);
printf("\n");
Update_Switch();
Update_Water_Leak();
Update_Relays(Relay_Status);
Update_Temperatures();
delay(500);
}
return 0;
}
void Update_Switch(void) {
Update_Analog(7);
if(AN_AD[7] > 2048) {
Switch = OFF;
}
else {
Switch = ON;
}
}
void Update_Water_Leak(void) {
Relay_Status |= K3; // Turn ON Water Sense Circuit
Update_Relays(Relay_Status);
delay(200);
Update_Analog(4); // Read Water Sense Circuit AD Counts
if(AN_AD[4] > WATER_LEAK_THRESHOLD) {
Water_Leak = ON;
}
else {
Water_Leak = OFF;
}
Relay_Status &= ~ K3; // Turn OFF Water Sense Circuit
Update_Relays(Relay_Status);
}
void Update_Temperatures(void) {
float sample;
unsigned int average;
int i;
// Calculate Temperature for Cold Water Line
average = 0;
for(i=0; i<5; i++) { // take 5 reading and average
Update_Analog(5); // to smooth out the reading
average += AN_AD[5];
}
average = average / 5;
sample = ((float)T_AD_COUNTS / average) - 1;
sample = (float)R_LOAD / sample;
sample = sample / (float)R_ROOM_TEMP;
sample = log(sample);
sample /= (float)T_BETA;
sample += 1.0 / ((float)ROOM_TEMP_NOM +275.15);
sample = 1.0 / sample;
sample -= 273.15;
Temp_Cold_Line = sample;
// Calculate Temperature for Hot Water Line
average = 0;
for(i=0; i<5; i++) { // take 5 reading and average
Update_Analog(6); // to smooth out the reading
average += AN_AD[6];
}
average = average / 5;
sample = ((float)T_AD_COUNTS / average) - 1;
sample = (float)R_LOAD / sample;
sample = sample / (float)R_ROOM_TEMP;
sample = log(sample);
sample /= (float)T_BETA;
sample += 1.0 / ((float)ROOM_TEMP_NOM +275.15);
sample = 1.0 / sample;
sample -= 273.15;
Temp_Hot_Line = sample;
// Set Alarm if Hot Water < Cold Water + 10% * Cold Water
if(Temp_Hot_Line < (Temp_Cold_Line + (Temp_Cold_Line * .1))) {
Relay_Status |= K2;
}
else {
Relay_Status &= ~K2;
}
}
void Update_Analog(unsigned char channel) {
unsigned int adc, input;
unsigned char buf[3];
wiringPiSPISetup(1, 100000);
input = 0x0600 | (channel << 6);
buf[0] = (input >> 8) & 0xff;
buf[1] = input & 0xff;
buf[2] = 0;
digitalWrite(PIN_EN_AD, LOW);
wiringPiSPIDataRW(1,buf,3);
adc = ((buf[1] & 0x0f ) << 8) | buf[2];
digitalWrite(PIN_EN_AD, HIGH);
AN_AD[channel] = adc;
}
void Update_Relays(unsigned char status) {
unsigned char buf[2];
if(Switch == ON || Water_Leak == ON) {
status |= K1;
}
else {
if(Switch == OFF && Water_Leak == OFF) {
status &= ~K1;
}
}
buf[0] = status;
wiringPiSPISetup(0, 100000);
wiringPiSPIDataRW(0,buf,1);
digitalWrite(PIN_EN_K, LOW);
delay(1);
digitalWrite(PIN_EN_K, HIGH);
}
void Initialize_Pi_Hardware(void) {
// SPI CS Enable Lines
pinMode(PIN_EN_AD, OUTPUT);
pinMode(PIN_EN_K, OUTPUT);
}
]]>
To get complete specs on each module, click on the links below.
From left to right and clockwise:
Here is the GPIO Mapping:
All of the modules shown above can be run at the same time. Also, each module has a spare GPIO selector jumper, meaning that some I/O modules can be doubled up. Need 16 Analog Inputs? no problem. Need 32 digital Inputs? No problem.
We have some really neat projects lined up for these modules, make sure to join our newsletter (at the bottom of this page) to stay up to date with what is coming up!
Thanks.
PS - Check out the home page for Black Friday Deals and Discounts!
]]>From Left to right: RPi 3, RS485 Interface, 8 Channel Analog Input (4-20mA, VDC and Thermistor), and 8 Channel Relay driver with 2 Relays (10 Amp Contacts) Populated.
Coming within days is the 8 channel Digital input (DC for AC Voltage input) and 2 channel Analog output (4-20mA and simultaneous VDC).
As can be seen, each module has a dual GPIO expansion port that allows as many (or as little) modules to be connected as required for a given project - and we have some pretty awesome projects lined up to share as instructables with everyone! Also, external power (typically 24 VDC) can be applied to any interface and there is no loading on the Pi's 3.3 VDC power supply. Each module has a 5V to 3.3V LDR (Low dropout regulator).
I'll share the next round of modules as soon as they're unpacked!
]]>
This interface is powered by a PIC18F45K20 micro, has RS485 Modbus RTU protocol, and the output dual DA Converters are the MCP4922 DAC which has 12 bit resolution and an SPI interface.
Here is a simplified schematic of one of the outputs from this interface:
Here is how the math works:
1. Typically, the DAC will run from 3.3VDC and the reference will also be 3.3VDC
2. To allow for overange and "headroom", the full scale Vin will be 3 VDC which corresponds to 37214 DA Counts (3/3.3 * 4096)
3. Basic Op Amp theory states 3 VDC Vin will then appear across R1 (let's say the standard 499R resistor is actually 500 Ohms to make everything cleaner)
4. Current flow through R1 will be 3VDC/500 Ohms = 0.006 A or 6 mA.
5, The same 6 mA will flow through R2, giving a voltage across R2 of .006A * 330 Ohm = 1.98 V
6. Basic Op Amp theory states that the voltage across R2 will equal the same voltage across R3, therefore the current flowing through R3 = 1.98 V / 100 R = 19.8 mA for Aout
With a little bit of tweaking on the Max defined DA Counts for 20 mA, the above circuit works exceptionally well. We use this in various products in our industrial line and also in the Widgetlords product offering as follows:
The V+ power for this type of circuit is typically 24 VDC to allow for output "Drive". Typically process instrumentation that accepts 4-20mA signal will have "Load" resistor of 250 Ohms (or less). At 24 VDC power and given that the above circuit will have a voltage loss of 2 VDC (give or take), the above wold be able to "Drive" up to 4 "Loads" in series. (Each Load resistor at 250 Ohms with 20 mA flow will have 5 VDC across the load). Simple, and clean.
Join our newsletter for information on projects and new product releases.
Enjoy!
]]>
From left to right: RPI 3, Pi-SPi-RS485, VP-TX100-CO Transmitter complete with MQ3 solid state sensor, and the Modbus VP-RDU Display.
The Pi-SPi-RS485 has some pretty cool features like dual GPIO ports for easy expansion, dual terminal blocks and dual RJ45 jacks for Cat5e cable connections. The wiring for the RJ45 is printed right on the board, and power for remote devices like the display is carried over the Cat5e cable.
Another feature of the Pi-SPi-RS485 is the remote Field Power Input - the only connection is the GND between the field power and the RPi power. Also the module has it's own LDO 3.3V regulator to minimize loading on the Pi's power supply.
Since both transmitter and display have RS485 and Modbus IO capability, the maximum distance between the two (with the Pi-SPi-RS485 and RPi 3 in between, more or less) can be up to 4000 feet - that's almost a mile!. All the RS485 drivers used in these products have ESD protection as a standard features.
The footprint of the Pi-SPi-RS485 is identical to the RPi 3, allowing for some flexible mounting as shown in these pics:
The dual GPIO ports on either side of the module allow for easy expansion for other modules.
More information on the Pi-SPi-RS485 can be found at:
Finally, this unit is offered in kit form with all the SMD parts already mounted, all the user has to do is solder on the through hole components. The unit is also offered fully assembled and factory tested.
More modules coming very, very soon!
]]>
The CO sensor is the brown device that looks like a AA battery. To the right are the %RH and Temperature sensors. This circuit works equally well with Zigbee and 900 MHz modules, and the Roving Networks Wi-Fi and BLuetooth modules.
Here is the battery circuit based on the Microchip MCP1256 chip:
The V_BAT signal goes to the PIC (PIC18LF14K22) to monitor the battery voltage. This signal used to trigger a transmission on low battery voltage. The PS_SL signal is a control signal from the PIC to put the MCP1256 into Low Power Mode while the PIC and Radio Module are sleeping. During sleep mode the MCP1256 has a minimal current draw of 0.1uA, with a higher output ripple.
]]>
Here is a pic of our wired water leak sensor pcb:
The processor is a PIC18LF14K22, and the circuitry also supports (you guessed it) a temperature sensor, an optional humidity sensor, an audible, and a dipswitch which is used to select a sensitivity.
Here is the actual water leak detection circuit:
The EN_H2O line is driven by the PIC IO line which turns on the 3.3 VDC to the J5 pins for about 1 second. The J5 and J6 pins are stainless steel screws about 1" apart. The V_H2O line goes to an A/D pin on the and the voltage detected easily translates to a reading of water conductivity.
This install saved us thousands of dollars worth of damage if we had not bee notified in time. The rest of the system consists of a wireless gateway and "Enviro Cloud" web based software (see www.vpprocess.com).
Here is a pic of the detector with it's case on:
And here is our wireless version of the water leak detector:
Water leak damage is one of the leading insurance claims and causes billions of damage every year. I was glad I dodged that one :)
Save]]>
The "must have" design criteria for this project had to have these minimum features:
and a few other wish list items. The design team (me :) ) was given 4 weeks to go from concept, to schematic, to board layout, to prototype, to test, and finally to beta test in a customer's location.
I am a firm believer in "cut and paste" and "if it ain't broke, don't fixit".
Quite a bit of the design was taken from previous products and pasted together. (parts of this design can be found in other products on this website and related blog posts!)
The PIC18LF66K series was chosen for its low cost, IO count, ease of programming and low power consumption. Even though the PIC has analog inputs, I decided to use the MCP3208 external A/D converter - the resolution was good enough for the application and I already had software libraries built for it. The one sensor I did not have experience with and spent the most time on was the pressure sensor. I finally chose an SPI type interface sensor because it was just too easy to implement.
Fortunately, we already had a display module as a component (128 x 64 white on blue) and the software function libraries, so that part was easy. The rest of the project was cut and pasted (literally on paper !!) before starting the schematic.
I have learned the hard way that even when under pressure, it saves time to make enough time to do things right - proofread schematics (especially against prior designs to catch rookie mistakes), recheck and validate artwork before releasing to production, and my favorite, always have a "heartbeat" LED designed into the project - it's the equivalent of the "Hello World" scenario when first starting the software side. (I still get a kick every time I apply power, there's no smoke, a bit of code, and the LED starts blinking!! )
At the end, a very enjoyable and rewarding project - everything worked just fine (you can see in the above pictures there are no "hack and whacks" - it's the rev A prototype), and most importantly, we have a happy customer. :)
]]>
VP-TX-190 front view:
VP-TX-190 Rear View:
In this circuit, the processor used is a PIC18LF14K22 and the thermistor input circuit is:
Simple, right? The +V can be supplied from one of the processor pins, enabling the wireless application to have very low power drain during sleep modes. In this example, the thermistor used is a 10K type with a Beta value of 3380. (There are many good articles available on the web explaining the theory behind thermistors, Beta values, etc.) R2, C1 and R3 is a high pass filter to help eliminate high frequency noise.
In all of our circuits that use thermistors, we use the Steinhart-Hart equation to get the actual temperature value in Degrees C. By using this equation, the +V supply can be any value, the AD counts are based on the reference input to the AD converter, in our case, the supply voltage to the PIC is 3.3 VDC and the V+ (whether from the power supply or PIC pin) is also 3.3 VDC
This code excerpt (we write all our application code for PIC based products in C) shows how the simple circuit above coupled with the Steinhart-Hart equation gives a temperature value:
// Code based on PIC18LF14K22 Processor
// V+ turned on by the PIC pin C3
// Channel 3 used for temperature input THv
#include <math.h>
#define R_LOAD 10000.0
#define R_ROOM_TEMP 10000.0 /* For 25 Deg C */
#define T_BETA 3380.0
#define T_AD_COUNTS 1024.0 /* 10 bit AD */
#define ROOM_TEMP_NOM_T1 25.0 /* For 25 Deg C */
int Update_Temperature(void)
{
int i;
unsigned int average;
float sample;
TRISCbits.TRISC3 = 0; /* Define Pin C3 As Output */
LATCbits.LATC3 = 1; /* Turn ON Thermistor*/
TRISAbits.TRISA4 = 1;
ANSELbits.ANSEL3 = 1;
ADCON2 = 0b10000000;
ADCON1 = 0b00000000;
ADCON0 = 0b00001101; /* Select Channel 3*/
average = 0;
ConvertADC();
while(BusyADC());
average = ReadADC();
LATCbits.LATC3 = 0; /* Turn OFF Thermistor*/
/* Here is the Steinhart-Hart temperature calculation */
sample = (T_AD_COUNTS / average) -1;
sample = R_LOAD / sample;
sample = sample / R_ROOM_TEMP;
sample = log(sample);
sample /= T_BETA;
sample += 1.0 / (ROOM_TEMP_NOM_T1 + 273.15);
sample = 1.0 / sample;
sample -= 273.15;
return (int)(sample);
}
int ReadADC(void)
{
return (((unsigned int)ADRESH)<<8)|(ADRESL);
}
void ConvertADC(void)
{
ADCON0bits.GO = 1;
}
char BusyADC(void)
{
return(ADCON0bits.GO);
}
]]>
Starting from the top center and going clockwise:
And the last piece to show you, the desktop of the RPi via the VNC viewer:
This screen shot shows the STDIO window of the analog inputs in AD Counts and mA Readings.
The test parameters are as follows:
You can find the interfaces listed above (Tech info, schematics, prices, etc) at these links:
Raspberry Pi Analog Input Module
LCD Display 4 Line x 20 Character
The following test source code works for both earlier RPi's and the current RPi 3 release. Remember to initialize the SPI and Serial on the RPi.
Finally, for updates on new projects and products, join our newsletter at the bottom of this page. Thanks and Enjoy!
/*
* main.c
*
* Copyright 2016 <pi@raspberrypi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
/*
* Initialize the SPI and Serial ports on the RPi before compiling
* Compile, Build and Make as sudo in Geanie C compiler
* Code tested on RPI and Jessie OS
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
// wiringPi Include Header Files
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <wiringSerial.h>
// Define Pins for Dipswitch
#define PIN_SW1 2
#define PIN_SW2 3
#define PIN_SW3 4
#define PIN_SW4 17
#define PIN_SW5 27
#define PIN_SW6 22
#define PIN_SW7 24
#define PIN_SW8 23
// Define Pin for RS485 Direction
// Low = Receive, High = Transmit
#define PIN_DIR 25
// Define Pins for SPI Chip Enables
#define PIN_EN_LED 18
#define PIN_EN_AD 7
// Define mA settings
// 20 mA into 150Ohms = 3 Vdc / 3.3 Vdc full scale * 4096 Counts
#define mA_20 3723
#define mA_Fault 2.5 // 2.5 mA
#define mA_Trip 12.5 // 12.5 mA
// Define MODBUS ID Settings
#define MODBUS_ID_RELAY 128
#define MODBUS_ID_DISPLAY 101
// Prototypes
void Initialize_Pi_Hardware(void);
int Read_Switch(void);
void Update_Leds(void);
void Update_Trip_Points(void);
void Update_Analog(unsigned char channel);
void Update_Uart_Relay_Output(void);
void Update_Uart_Remote_Display(void);
unsigned int MB_crc16(char *p, unsigned char n);
// Variables
unsigned AN_AD[8];
float AN_mA[8];
int Switch;
int fd;
unsigned char Relay_Status;
// main
int main(void) {
int i;
// Initialize
wiringPiSetupGpio();
Initialize_Pi_Hardware();
digitalWrite(PIN_EN_LED, HIGH);
digitalWrite(PIN_EN_AD, HIGH);
// Set RS485 Transceiver to Receive
digitalWrite(PIN_DIR, LOW);
while(1)
{
Switch = Read_Switch();
// Update all 8 Analog Inputs
Update_Analog(0);
Update_Analog(1);
Update_Analog(2);
Update_Analog(3);
Update_Analog(4);
Update_Analog(5);
Update_Analog(6);
Update_Analog(7);
// Print Analog Input Info to STDIO
printf("ID = %d \n", Switch);
for(i = 0; i < 8; i++) {
printf("Channel AN%d = %d ADC, %5.2f mA \n", (i+1), AN_AD[i], AN_mA[i]);
}
printf("\n");
// Update Leds on 8AI, ON if input > 2.5 mA
Update_Leds();
// Update Remote Relays, Each Relay On if mA > 12.5 mA
Update_Trip_Points();
// Send Relay info to Remote Module via Modbus
Update_Uart_Relay_Output();
// Delay to allow Remote Module to respond
delay(500);
// Send Analog info to Remote Display Unit
Update_Uart_Remote_Display();
// Delay to allow Remote Display to respond
delay(500);
}
return 0;
}
// Read Analog Info by Channel from MCP3208
void Update_Analog(unsigned char channel) {
unsigned int adc, input;
unsigned char buf[3];
// Initialize SPI, - using slow speed
wiringPiSPISetup(1, 100000);
// Define inpu channel parameters fro MCP3208
input = 0x0600 | (channel << 6);
buf[0] = (input >> 8) & 0xff;
buf[1] = input & 0xff;
buf[2] = 0;
// Enable the CS Line
digitalWrite(PIN_EN_AD, LOW);
// Write / Read data from MCP3208
wiringPiSPIDataRW(1,buf,3);
// Get AD Counts
adc = ((buf[1] & 0x0f ) << 8) | buf[2];
// Disable the CS Line
digitalWrite(PIN_EN_AD, HIGH);
// Save Analog info as ad Counts
AN_AD[channel] = adc;
// Save Analog info as mA
AN_mA[channel] = (float) adc * 20 / mA_20;
}
// Update the Status LEDs
void Update_Leds(void) {
unsigned char buf[2];
unsigned char value;
value = 0;
if(AN_mA[0] > mA_Fault) {
value |= 0x01;
}
if(AN_mA[1] > mA_Fault) {
value |= 0x02;
}
if(AN_mA[2] > mA_Fault) {
value |= 0x04;
}
if(AN_mA[3] > mA_Fault) {
value |= 0x08;
}
if(AN_mA[4] > mA_Fault) {
value |= 0x10;
}
if(AN_mA[5] > mA_Fault) {
value |= 0x20;
}
if(AN_mA[6] > mA_Fault) {
value |= 0x40;
}
if(AN_mA[7] > mA_Fault) {
value |= 0x80;
}
buf[0] = value;
// Intialize the SPI - slow speed
wiringPiSPISetup(0, 100000);
// Write Data to the 74HC595
wiringPiSPIDataRW(0,buf,1);
// Enable, Delay, Disable the CS Line
digitalWrite(PIN_EN_LED, LOW);
delay(1);
digitalWrite(PIN_EN_LED, HIGH);
}
// Update the Relay Status to be sent to the remote 8 channel Relay module
void Update_Trip_Points(void) {
unsigned char value;
value = 0;
if(AN_mA[0] > mA_Trip) {
value |= 0x01;
}
if(AN_mA[1] > mA_Trip) {
value |= 0x02;
}
if(AN_mA[2] > mA_Trip) {
value |= 0x04;
}
if(AN_mA[3] > mA_Trip) {
value |= 0x08;
}
if(AN_mA[4] > mA_Trip) {
value |= 0x10;
}
if(AN_mA[5] > mA_Trip) {
value |= 0x20;
}
if(AN_mA[6] > mA_Trip) {
value |= 0x40;
}
if(AN_mA[7] > mA_Trip) {
value |= 0x80;
}
Relay_Status = value;
}
// Send via MODBUS Relay info to the Relay module
void Update_Uart_Relay_Output(void) {
unsigned char i, index;
char tx_buffer[11];
unsigned int checksum;
// Open Serial Port and Initialize
//fd = serialOpen("/dev/ttyAMA0", 19200); // For RPi < 3
fd = serialOpen("/dev/ttyS0", 19200); // For RPi = 3
if(fd < 0)
{
printf("Error opening Serial Port \nn");
return;
}
index = 0;
tx_buffer[index++] = MODBUS_ID_RELAY; // MODBUS ID for slave relay module
tx_buffer[index++] = 15; // Function 15 = write multiple coils
tx_buffer[index++] = 0; // Start Address High Byte
tx_buffer[index++] = 0; // Start Address Low Byte
tx_buffer[index++] = 0; // Qty Coils High Byte
tx_buffer[index++] = 8; // Qty Coils Low Byte
tx_buffer[index++] = 1; // Byte Count
tx_buffer[index++] = Relay_Status; // Data Byte (8 Coils)
checksum = MB_crc16(tx_buffer,index);
// Checksum Low Byte, High Byte, Sent Little Endian
tx_buffer[index++] = (unsigned char)(checksum & 0x00ff);
tx_buffer[index++] = (unsigned char)((checksum >> 8) & 0x00ff);
digitalWrite(PIN_DIR, HIGH); // Set RS485 to TX
delay(5); // Allow lines to settle
for(i=0; i<index; i++) {
serialPutchar(fd, tx_buffer[i]);
}
delay(50); // Allow last byte stop bit
digitalWrite(PIN_DIR, LOW); // Set RS485 to RX
serialClose(fd);
}
// Read the Dipswitch GPIO lines
int Read_Switch(void) {
int value;
value = 0;
if(!digitalRead(PIN_SW1)) {
value |= 0x01;
}
if(!digitalRead(PIN_SW2)) {
value |= 0x02;
}
if(!digitalRead(PIN_SW3)) {
value |= 0x04;
}
if(!digitalRead(PIN_SW4)) {
value |= 0x08;
}
if(!digitalRead(PIN_SW5)) {
value |= 0x10;
}
if(!digitalRead(PIN_SW6)) {
value |= 0x20;
}
if(!digitalRead(PIN_SW7)) {
value |= 0x40;
}
if(!digitalRead(PIN_SW8)) {
value |= 0x80;
}
return value;
}
// Initialize the RPi hardware GPIO lines
void Initialize_Pi_Hardware(void) {
// SPI CS Enable Lines
pinMode(PIN_EN_LED, OUTPUT);
pinMode(PIN_EN_AD, OUTPUT);
// Dipswitch Input Lines
pinMode(PIN_SW1, INPUT);
pinMode(PIN_SW2, INPUT);
pinMode(PIN_SW3, INPUT);
pinMode(PIN_SW4, INPUT);
pinMode(PIN_SW5, INPUT);
pinMode(PIN_SW6, INPUT);
pinMode(PIN_SW7, INPUT);
pinMode(PIN_SW8, INPUT);
// RS485 Direction Line, 0 = Receive, 1 = Transmit
pinMode(PIN_DIR, OUTPUT);
}
// MODBUS RTU Error Checkum calculation using Polynomial Method
unsigned int MB_crc16(char *p, unsigned char n) {
unsigned char i;
unsigned int crc, poly;
crc = 0xffff;
poly = 0xa001;
while(n--) {
crc ^= *p++;
for(i = 8; i != 0; i--) {
if(crc&1) {
crc = (crc>>1) ^ poly;
}
else {
crc >>= 1;
}
}
}
return crc;
}
// Update the Remote Display via MODBUS
void Update_Uart_Remote_Display(void) {
unsigned char i, index;
char tx_buffer[97];
unsigned int checksum;
// Open Serial Port and Initialize
//fd = serialOpen("/dev/ttyAMA0", 19200); // For RPi < 3
fd = serialOpen("/dev/ttyS0", 19200); // For RPi = 3
if(fd < 0)
{
printf("Error opening Serial Port \nn");
return;
}
index = 0;
tx_buffer[index++] = 101; // MODBUS ID for slave display module
tx_buffer[index++] = 16; // Function 16 = write multiple holding registers
tx_buffer[index++] = 0; // Start Address High Byte
tx_buffer[index++] = 0; // Start Address Low Byte
tx_buffer[index++] = 0; // Qty Regsiters High Byte
tx_buffer[index++] = 43; // Qty Registers Low Byte
tx_buffer[index++] = 84; // Byte Count
// Update the 4 line x 20 character data buffers with analog info
sprintf(&tx_buffer[index],"A1= %5.2f A5= %5.2f \n", AN_mA[0], AN_mA[4] );
index += 20;
sprintf(&tx_buffer[index],"A2= %5.2f A6= %5.2f \n", AN_mA[1], AN_mA[5] );
index += 20;
sprintf(&tx_buffer[index],"A3= %5.2f A7= %5.2f \n", AN_mA[2], AN_mA[6] );
index += 20;
sprintf(&tx_buffer[index],"A4= %5.2f A8= %5.2f \n", AN_mA[3], AN_mA[7] );
index += 20;
tx_buffer[index++] = 0;
tx_buffer[index++] = 0; // status LED 1 , not used
tx_buffer[index++] = 0;
tx_buffer[index++] = 0; // status LED 2 not used
tx_buffer[index++] = 0;
tx_buffer[index++] = 0; // audible driver not used
checksum = MB_crc16(tx_buffer,index);
// Checksum Low Byte, High Byte, Sent Little Endian
tx_buffer[index++] = (unsigned char)(checksum & 0x00ff);
tx_buffer[index++] = (unsigned char)((checksum >> 8) & 0x00ff);
digitalWrite(PIN_DIR, HIGH); // Set RS485 to TX
delay(10); // Allow lines to settle
for(i=0; i<index; i++) {
serialPutchar(fd, tx_buffer[i]);
}
delay(100); // Allow last byte stop bit
digitalWrite(PIN_DIR, LOW); // Set RS485 to RX
serialClose(fd);
}
]]>
This design is based on the MCP3208 8 channel 12 Bit Analog to Digital converter form Microchip.
PCB Assembly complete with PIC Processor Module:
Schematic:
Each analog input 0 to 20 mA signal is convert to a voltage across the 150 Ohm Load Resistor giving a 0 to 3.0 V input to the MCP3208.
PCB Assembly with PIC Processor PCB detached:
Some of the design criteria was to have the module be compatible with the Raspberry Pi, have RS485 I/O, have MODBUS RTU communication and have protection for the input circuits.
Here is the full specification:
Schematic Page 2:
By removing the PIC PCB, the device now becomes Raspberry Pi Compatible:
For information regarding the PIC module, please see the post for the VP-EC-8KO.
This sample code uses the wiringPi library and the Geany C compiler. The code has been tested for:
/*
* main.c
*
* Copyright 2016 <pi@raspberrypi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
// Define Pins RPi V2 Series B
#define PIN_SW1 2
#define PIN_SW2 3
#define PIN_SW3 4
#define PIN_SW4 17
#define PIN_SW5 27
#define PIN_SW6 22
#define PIN_SW7 24
#define PIN_SW8 23
#define PIN_08 14 // Used for testing UART Leds Tx and Rx
#define PIN_10 15
#define PIN_EN_LED 18 // CS for LEDS (74HC595)
#define PIN_EN_AD 7 // CS for Analog Inputs MCP3208
#define mA_20 3723 // 20 mA * 150Ohms = 3 Vdc/3.3 Vdc full scale * 4096 Counts
#define mA_Fault 372 // 2 mA Fault level in AD Counts
// Function Prototypes
void Initialize_Pi_Hardware(void);
int Read_Switch(void);
void Update_Leds(void);
unsigned int Update_Analog(unsigned char channel);
// Variables
unsigned int AN_AD[8];
int Switch;
int main(void) {
int i;
wiringPiSetupGpio(); // Initialize the wiringPi GPIO
Initialize_Pi_Hardware(); // Set the GPIO Bit directions
digitalWrite(PIN_EN_LED, HIGH); // Set the EN LED CS HIGH
digitalWrite(PIN_EN_AD, HIGH); // Set the EN AD CS HIGH
while(1)
{
Switch = Read_Switch(); // Read the 8 Point Dip Switch
AN_AD[0] = Update_Analog(0); // Read Channel A0 AD Counts from MCP3208
AN_AD[1] = Update_Analog(1); // Read Channel A1 AD Counts
AN_AD[2] = Update_Analog(2); // Read Channel A2 AD Counts
AN_AD[3] = Update_Analog(3); // Read Channel A3 AD Counts
AN_AD[4] = Update_Analog(4); // Read Channel A4 AD Counts
AN_AD[5] = Update_Analog(5); // Read Channel A5 AD Counts
AN_AD[6] = Update_Analog(6); // Read Channel A6 AD Counts
AN_AD[7] = Update_Analog(7); // Read Channel A7 AD Counts
printf("ID = %d \n", Switch); // Print the Data
for(i = 0; i < 8; i++) {
printf("Channel AN%d = %d ADC, %0.2f mA \n", (i+1), AN_AD[i], (float)AN_AD[i] * 20 / mA_20);
}
printf("\n");
Update_Leds(); // Update AN1 thru A8 LEDs using the 74HC595
delay(1000); // Delay 1 Second loop
}
return 0;
}
// Update Analog Inputs using the MCP3208
unsigned int Update_Analog(unsigned char channel) {
unsigned int adc, input;
unsigned char buf[3];
wiringPiSPISetup(1, 100000);
input = 0x0600 | (channel << 6);
buf[0] = (input >> 8) & 0xff;
buf[1] = input & 0xff;
buf[2] = 0;
digitalWrite(PIN_EN_AD, LOW);
wiringPiSPIDataRW(1,buf,3);
adc = ((buf[1] & 0x0f ) << 8) | buf[2];
digitalWrite(PIN_EN_AD, HIGH);
return adc;
}
// Update the A1 thru A8 LEDs using the 74HC595
// If the AD Counts are > than the AD Fault Counts, the respective Ax LED turns on
void Update_Leds(void) {
unsigned char buf[2];
unsigned char value;
value = 0;
if(AN_AD[0] > mA_Fault) {
value |= 0x01;
}
if(AN_AD[1] > mA_Fault) {
value |= 0x02;
}
if(AN_AD[2] > mA_Fault) {
value |= 0x04;
}
if(AN_AD[3] > mA_Fault) {
value |= 0x08;
}
if(AN_AD[4] > mA_Fault) {
value |= 0x10;
}
if(AN_AD[5] > mA_Fault) {
value |= 0x20;
}
if(AN_AD[6] > mA_Fault) {
value |= 0x40;
}
if(AN_AD[7] > mA_Fault) {
value |= 0x80;
}
buf[0] = value;
wiringPiSPISetup(0, 100000);
wiringPiSPIDataRW(0,buf,1);
digitalWrite(PIN_EN_LED, LOW);
delay(1);
digitalWrite(PIN_EN_LED, HIGH);
}
// Read the Dipswitch as a value from 0 thru 255, to be used as the Modbus ID value
int Read_Switch(void) {
int value;
value = 0;
if(!digitalRead(PIN_SW1)) {
value |= 0x01;
}
if(!digitalRead(PIN_SW2)) {
value |= 0x02;
}
if(!digitalRead(PIN_SW3)) {
value |= 0x04;
}
if(!digitalRead(PIN_SW4)) {
value |= 0x08;
}
if(!digitalRead(PIN_SW5)) {
value |= 0x10;
}
if(!digitalRead(PIN_SW6)) {
value |= 0x20;
}
if(!digitalRead(PIN_SW7)) {
value |= 0x40;
}
if(!digitalRead(PIN_SW8)) {
value |= 0x80;
}
return value;
}
// Initialze the GPIO pin directions
void Initialize_Pi_Hardware(void) {
pinMode(PIN_08, OUTPUT);
pinMode(PIN_10, OUTPUT);
pinMode(PIN_EN_LED, OUTPUT);
pinMode(PIN_EN_AD, OUTPUT);
pinMode(PIN_SW1, INPUT);
pinMode(PIN_SW2, INPUT);
pinMode(PIN_SW3, INPUT);
pinMode(PIN_SW4, INPUT);
pinMode(PIN_SW5, INPUT);
pinMode(PIN_SW6, INPUT);
pinMode(PIN_SW7, INPUT);
pinMode(PIN_SW8, INPUT);
}
]]>
SUT fully assembled:
Schematic Page 1:
All of the circuitry for the converter can be powered from the USB port, in higher power applications, the design incorporates an optional power supply, the VP-PSDC-05-033. The heart of the design is the FTDI FT232RL USB converter IC. The TTL levels are available on the RJ11 jack or pin header.
Basic version with USB, Raspberry Pi and Zigbee headers.
Bottom side PCB view:
Schematic Page 2:
This schematic shows the Zigbee module connections, the Raspberry Pi Connections and the RS232 Interface. In some cases where only the USB to Zigbee are required (no other sections populated), there are jumpers available (R48 and R49) to provide a direct connection between the USB and Zigbee modules.
SUT and Raspberry Pi connected:
Schematic Page 3:
This schematic shows the RS485 connections. If the Raspberry Pi Uart is not used, or does not want to drive the RS485 direction, there is an Automatic Direction Circuit based on a 555 Timer. It senses whenever there are transmissions present on the TX line and switches the direction control of the RS485 drive IC, (the MAC3072 or equivalent). This circuit has been tested and used in applications running at 9600 BAUD all the way up to 115.2K BAUD with no problems - this is a staple in our tech department.
SUT in kit form:
Schematic Page 4:
I personally like lots of LED's, this circuit shows the logic for all the TX and RX LED's available for all the various in's and out's.
There you have it - a multi-use Serial Converter Tool!
Oh, almost forgot - the PCB design was done so the final assembly would fit into a standard SERPAC enclosure as shown:
]]>
The VP-EC-RDU
The design is based on the PIC18F45K20 processor, has the ICSP port available for programming and product development, a RS485 port, etc.
Here are the schematics:
Here is the VP-EC-RDU in the enclosure with Graphic Overlay:
Two versions of this product are available:
Model: VP-EC-RDU is the complete unit with case, assembled and tested
Model: VP-EC-RDU-PCB is the same except without the case and graphic label.
Address: 0
Data: Menu = 0x01
UP = 0x02
DOWN = 0x04
ENTER = 0x08
The LCD uses both high and low bytes of the Holding registers and displays the ASCII characters as follows:
Holding Register Address - Description
0 to 9 LCD Line 1 (20 Character ASCII String)
10 to 19 LCD Line 2 (20 Character ASCII String)
20 to 29 LCD Line 3 (20 Character ASCII String)
30 to 39 LCD Line 4 (20 Character ASCII String)
40 Status LED 1
41 Status LED 2
42 Audible 0 = OFF, 1 = ON
Status LED States are defined as follows:
OFF 0x00
GREEN 0x01
GREEN SLOW FLASH 0x11
GREEN FAST FLASH 0x21
AMBER 0x02
AMBER SLOW FLASH 0x12
AMBER FAST FLASH 0x22
RED 0x04
RED SLOW FLASH 0x14
RED FAST FLASH 0x24
Here are other views of the display:
]]>
The VP-EC-8KO (Final Version)
The Schematic
The design is based on the PIC18F45K20, and as with all of our PIC based projects, the ICSP (In Circuit Serial Programming Port) is available for programming the device, as well as making each device a development platform for expanding the capabilities or dreaming up new applications.
The original design was based on a version that would also be compatible with the Raspberry Pi: it had a separate cpu module that has the same GPIO bus structure and the Raspberry Pi, but was a lot cheaper to produce. Also, there was a provision to have a Zigbee module for wireless applications.
Complete original unit with the Raspberry Pi:
Complete original unit with the PIC_PI PCB:
Here is the PIC_PI PCB and schematic:
Finally, the module had to fit into a readily available DIN rail mount enclosure, like the one from BUD Industries.
]]>
Kit View
As we all know, with windows based computers and various versions of windows (XP, Vista, 7, 8, and whatever comes next), not all versions of software programs still work. Personally, I was a huge Hyperterminal fan back in the old days. So, I was scratching for ideas of how to simply see the communication data strings that were being passed back and forth between the Pi and the Zigbee module.
Then I had one of those Aha! moments. Our serial converter tool supports the Zigbee wireless module, has the Pi interface connection, and of course, the USB connection to the computer. The Digi International X-CTU program is a free download from their website ( http://www.digi.com/support ) and once the serial protocols were set up (we typically use 9600 Buad, N81), and you go to the Terminal Page and select Show Hex, here is what you see:
Using the Serial Utility Tool and the X-CTU program, you can also see data traffic on RS485, RS232, TTl, USB and of course, the uart on the Pi traffic. This is a very simple solution to see data traffic on a serial port.
Hope you find this useful, till next time.
Vytas
]]>