Measuring cards for a heat recovery system

From Pinguino
Jump to: navigation, search

This article is work in progress.

Moreno, an engineer from Italy working in industrial automation, has designed three boards to acquire temperature, analog and frequency signals and current draw of standard signal sensors. The data is sent via serial port (RS232 or RS485) to a superior system.

Moreno's project includes three measuring cards:

Project 1: Collecting filling level data of tanks

Userprojects moreno measuring card-01.jpg

This board collects filling levels of tanks. The sensors are connected to 2 external analog / digital converters (ADC) of type MCP3208 from Microchip. They are read from Pinguino via SPI. The averaged result of the conversion is send via serial port (RS232 or RS485) to a WAGO PLC. "Doing this directly with WAGO modules is too expensive", says Moreno. "I have to pay about 720 Euro for 16 channels. And I need a minimum of 30 channels. With PINGUINO I've done it for just 60 Euro!"

Board: Pinguino32-Micro using PIC32MX440

Features

  • 2 external 12 bit ADC MCP3208
  • Serial port (RS232 / RS485)

Links

Source

Here's the source code:


/*
Read16ChannelADC.pde

Read 2x8 12bit AD channels on 2 MCP3208
Average on NUMSAMPLEAVG (now 4) lectures for each channel
Create an ASCII HEX frame for the 16 channel
Transmit continuously frame on Serial port (if DEBUG is defined even on CDC channel)
27/03/2012 Ver. 1 Rev. 0 c. Moreno Manzini moreno at mediacom dot it

Licence Creative Commons 3.0 http://creativecommons.org/licenses/by-sa/3.0/

SPI routine inspired to http://www.arduino.cc/playground/Code/MCP3208
*/


//NOTE

// CDC.printf("%s",Str); go crazy if the length of the string is more than 64 Bytes

// Serial.xxx are alias of serial1xxx Es. Serial.begin serial1init@include <pinguinoserial1.c>

// Serial.printf is a blocking function



// Maximum transmission rate in mS
#define TxRate_mS           100
#define DEBUG               1
#define NUMSAMPLEAVG        4

// the 2 MCP3208 share SELPIN, SPICLOCK and DATAOUT in this manner I read 2 channel at the same time
// These are only digital IO can be placed everywhere
#define SELPIN             16 //Selection Pin
#define SPICLOCK           17 //Clock
#define DATAOUT            18 //MOSI
#define DATAIN1            19 //MISO 1
#define DATAIN2            20 //MISO 2
 
// Only a remind of serial1 pinout
#define SERIAL1RX          11 //RX of Serial 1 (RD2)
#define SERIAL1TX          12 //TX of Serial 1 (RD3)

//PIC32-PINGUINO-MICRO GREEN LED
#define ledPinG            32 // the number of the Green LED pin

int Count = 0;
int CtnAVG = 0;
int TimemS0,TimemS1;
int Data[16][NUMSAMPLEAVG],Avg[16],CRCSUM;
char Str[200],Str1[20];

void setup()
{                
   memset(&Data,0,sizeof(Data));

   //set pin modes
   pinMode(ledPinG, OUTPUT);
   pinMode(SELPIN, OUTPUT);
   pinMode(DATAOUT, OUTPUT);
   pinMode(DATAIN1, INPUT);
   pinMode(DATAIN2, INPUT);
   pinMode(SPICLOCK, OUTPUT);

   //disable device to start with
   digitalWrite(SELPIN,HIGH);
   digitalWrite(DATAOUT,LOW);
   digitalWrite(SPICLOCK,LOW);
   digitalWrite(ledPinG,LOW);

   //Initialize serial port to 9600Baud
   Serial.begin(9600);
}

//Read 2 Channel of AD Converter uno for each MCP3208
void ReadChannels(int Ch, int * ValAD1, int * ValAD2)
{
   int adcvalue1 = 0;
   int adcvalue2 = 0;
   int i;
   byte commandbits = 0B11000000; //command bits - start, mode, chn (3), dont care (3)

   //allow channel selection
   commandbits |= ((Ch-1)<<3);

   digitalWrite(SELPIN,LOW); //Select adc

   // setup bits to be written
   for (i=7; i>=3; i--)
   {
      digitalWrite(DATAOUT,commandbits&1<<i);

      //cycle clock
      digitalWrite(SPICLOCK,HIGH);
      digitalWrite(SPICLOCK,LOW);    
   }

   digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
   digitalWrite(SPICLOCK,LOW);
   digitalWrite(SPICLOCK,HIGH);  
   digitalWrite(SPICLOCK,LOW);

   //read bits from adc
   for (i=11; i>=0; i--)
   {
      adcvalue1+=digitalRead(DATAIN1)<<i;
      adcvalue2+=digitalRead(DATAIN2)<<i;
      
      //cycle clock
      digitalWrite(SPICLOCK,HIGH);
      digitalWrite(SPICLOCK,LOW);
   }

   digitalWrite(SELPIN, HIGH); //turn off device
   *ValAD1 = adcvalue1;
   *ValAD2 = adcvalue2;
}

void loop()
{
   TimemS0 = millis();

   //Read AD Converters
   for (Count = 0 ; Count < 8 ; Count++)
   ReadChannels(Count,&Data[Count][CtnAVG],&Data[Count+8][CtnAVG]);
   if (++CtnAVG >= NUMSAMPLEAVG)
   CtnAVG = 0;

   //Calculate Average Data
   for (Count = 0 ; Count < 16 ; Count++)
   Avg[Count] = (Data[Count][0]+Data[Count][1]+Data[Count][2]+Data[Count][3])/4;

   //Generate and transmit Frame
   CRCSUM = 0;
   sprintf(Str,"#01-%4.4X,%4.4X,%4.4X,%4.4X,",Avg[0],Avg[1],Avg[2],Avg[3]);
   for (Count = 0 ; Count < strlen(Str) ; Count++)    
   CRCSUM += Str[Count];
#ifdef DEBUG
   CDC.printf("%s",Str);
#endif
   Serial.printf("%s",Str);
   sprintf(Str,"%4.4X,%4.4X,%4.4X,%4.4X,",Avg[4],Avg[5],Avg[6],Avg[7]);
   for (Count = 0 ; Count < strlen(Str) ; Count++)    
   CRCSUM += Str[Count];
#ifdef DEBUG
   CDC.printf("%s",Str);
#endif
   Serial.printf("%s",Str);
   sprintf(Str,"%4.4X,%4.4X,%4.4X,%4.4X,",Avg[8],Avg[9],Avg[10],Avg[11]);
   for (Count = 0 ; Count < strlen(Str) ; Count++)    
   CRCSUM += Str[Count];
#ifdef DEBUG
   CDC.printf("%s",Str);
#endif
   Serial.printf("%s",Str);
   sprintf(Str,"%4.4X,%4.4X,%4.4X,%4.4X",Avg[12],Avg[13],Avg[14],Avg[15]);
   for (Count = 0 ; Count < strlen(Str) ; Count++)    
   CRCSUM += Str[Count];
#ifdef DEBUG
   CDC.printf("%s",Str);
#endif
   Serial.printf("%s",Str);
   sprintf(Str1,"=%4.4X\r\n",CRCSUM);
#ifdef DEBUG
   CDC.printf("%s",Str1);
#endif
   Serial.printf("%s",Str1);

   //Toggle Green LED
   digitalwrite(ledPinG, digitalread(ledPinG) ^ 1);

   //Total delay to TxRate_mS
#ifdef DEBUG
   TimemS1 = millis() - TimemS0;
   sprintf(Str1,"%4.4X\r\n",TimemS1);
   CDC.printf("%s",Str1);
#endif

   //If necessary delay to TxRate_mS
   TimemS1 = millis() - TimemS0;
   if (TimemS1 < TxRate_mS)
   delay(TxRate_mS - TimemS1);
}

Project 2: Measure board and data logger

Userprojects moreno measuring card-02.jpg

This is a heat recovery data logger which measures temperature with 4 sensors and the flow rate of water with 2 sensors. With the gathered data the amount of energy recovered will be calculated and the efficiency of the system monitored. The data are shown on the display and stored on SD card. Optionally it can be sent over an RS485 port.

Board: Pinguino32-Micro

Features

The device has:

  • 4 separate temperature channels (DS18B20)
  • 2 isolated counter input for FlowMeters (Int1-Int4)
  • 1 isolated digital Input
  • 3 Isolated digital output (Photomos 2,5A ASSR-1611, great device)
  • 1 RS485 port
  • 1 DS1306 SPI RTC (I used an SPI device to avoid the problem with UEXT connector because it is easy do an emulated SPI using standard IO). In this manner the UEXT port is free and I can use it as an expansion port.
  • 1 4x4 optional keyboard
  • 1 16x2 or 20x4 LCD display (I used lcdlib for 2x16 display and 20x4 display and both work perfectly).

Links




Project 3: Multi channel measure card

Userprojects moreno measuring card-03.jpg

This board is applied to a system for collecting hot wastewater in dyehouse plants. With the energy of the wastewater clean water used in the plant is heated. Moreno uses the internal 10 bit ADC of the Pinguino32-Micro with an external voltage reference of 2500 mV (LT1009-2,5). The diodes seen on the image are only used for polarity protection. The 124 ohm resistor on the analog input is sufficient to generate a drop of 2480 mV at a current of 20 mA.

Board: Pinguino32-Micro

Features

This board includes

  • 16 OneWire channels
  • 4 10 bit analog inputs to acquire standard signal inputs (live zero, 4-20 mA)
  • 2 isolated digital inputs (with interrupts)
  • A serial port (RS232 or RS485)

Links

Some other interesting posts related to moreno's projects

Some problems occurring during development and the solutions