ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
19 апреля
999509 Топик полностью
Гyдвин, волшебник (27.04.2020 19:01, просмотров: 890) ответил Гyдвин на Понимаю, что лепил из того, что было под рукой, тем не менее... Вот весь "датчик". Для закапывания в землю и подвешивания под крышу одинаковый. Отпилил лишние акселерометр, операционник, датчик вибрации и eeprom. Осталось то, что на картинке :) S1 - геркон. Радиомодуль на CC1101.
Вот стабильно работающий макет прошивы, работающий в течении уже нескольких суток для такой же платки-донора на MSP, присопливленной пятью проводками в модем Telit GL 868 Dual. Регулярно отправляет данные с двух беспроводных датчиков скрипту на HTTP сервере, получает в ответ уставку температуры включения вентилятора(если необходимо изменить дефолтную) и рулит им. Получает оттуда же в заданное время команду включения полива на XX минут. Хоть без крутого парсинга, но 

вполне уже созрела для испытаний "курятника". Из за лени применил sprintf() и прошива увеличилась вдвое - до 3.5 кб :) Осталось протянуть трубы и прикрутить PHP скрипт на сервер для вывода графиков, чтобы приступить к настройке и доводке ;)


/////////////////////////////////////////////////////////////////////////////

#define      VER     1        //  Telit  868 МГц 

#define      INTERVAL        5 * 75   // 5 минут * количество тиков в минутц - 75   
#define   IDS1            0x0076   // ID "воздушного" датчика
#define   IDS2            0x265a   // ID "земляного"  датчика





//#define   RF_POWER        0x40   // -5 dBm
//#define   RF_POWER        0x80   //  4 dBm
//#define   RF_POWER        0xC0   //  12 dBm
#define   RF_POWER        0x50   //  0 dBm


#define   OK              0x009A
#define   ACT             0x027D
#define   REG             0x0233
#define   CONNECT         0x020A
#define   HTTPOK          0x036B
//#define   NOACT           0x027C
//#define   NOREG1          0x0232 
//#define   NOREG2          0x0234


#define   T_ON             25     // температура включения вентилятора по-умолчанию
#define   TIMEV            100    // время выключения вентилятора  * 0.75 сек


//////////tst/////////////////////
// 3.5V  LF oscillator
// 20C - 10.14 kHz
//-10C -  9.17 kHz
//+45C - 11.29 kHz
//////////////////////////////////

#include <string.h>
#include "io430.h"
#include "cc110X.h"
#include "stdio.h"

#pragma diag_suppress=Pa082


void reset_modem(void);//
void init_modem(void); //
void debug(unsigned int c); //



#pragma location=0x1000 
__no_init const unsigned short MY_ID; // серийный номер по адресу 0x1000




volatile unsigned int code =0;
volatile unsigned char cnt_ch;

volatile unsigned int timeout =0;
volatile unsigned int del_075;
volatile unsigned int pattern =0;
volatile unsigned int pump =0;
volatile unsigned int vent =0;
volatile unsigned int tON_vent;
volatile unsigned int cnt_s_pump=0;
volatile unsigned int cnt_s_vent=0;


unsigned short bat1;  // напряжение батареи 1
unsigned short bat2;  // напряжение батареи 2
unsigned char  imp1;  // импеданс 1
unsigned char  imp2;  // импеданс 2
signed   char  tm1;   // температура 1
signed   char  tm2;   // температура 2


struct {
unsigned short id;   // ID датчика
unsigned short bat;  // напряжение батареи
unsigned char  imp;  // импеданс
signed   char  tm;   // температура
unsigned char  xxx[3] ;   
} rec_rx;


void work_sens(void)
{
  char len;
 
  if (FL_CC)
   {
    CLR_FL_CC;
    len=7;
    if(RFReceivePacket((char*)&rec_rx,(char*)&len))
    {
      if (len==6)
      {
       if (rec_rx.id == IDS1)
        {
           bat1=rec_rx.bat;  
           imp1=rec_rx.imp;  
           tm1=rec_rx.tm;   
        }
       if (rec_rx.id == IDS2)
        {
           bat2=rec_rx.bat;  
           imp2=rec_rx.imp;  
           tm2=rec_rx.tm;   
           if(tm2 > tON_vent) vent=TIMEV;  // включить вентилятор    
           // сам выключится через TIMEV, если температура упадет
        }
      }
     //debug(rec_rx.imp + (rec_rx.tm<<8));
     //debug(rec_rx.id);
    }
    TI_CC_SPIStrobe(TI_CCxxx0_SRX);  // перезапустим прием
   }
}

void clear_data(void)     // обнуление данных
{
   bat1=imp1=tm1=0;
   bat2=imp2=tm2=0;
}


void delay(unsigned int del)
{
  del_075=del;
  while(del_075) work_sens();

} 

void soft_reset(void)
{
   WDTCTL = WDT_MRST_0_064;             
   while(1);
}

void putchr(char c)
{
   while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
   UCA0TXBUF = c; 
}

void Send_UART(char * byte)
{
    for (;*byte;++byte) putchr (*byte);
    putchr(13);
}

void init_uart(void)
{
//////////////// настроим последовательный порт//////////////////////////////
        P1SEL |=  BIT1 + BIT2 ;                    // P1.1 = RXD, P1.2=TXD
        P1SEL2 |= BIT1 + BIT2 ;                    // P1.1 = RXD, P1.2=TXD
        UCA0CTL1 |= UCSSEL_2;                     // SMCLK
        UCA0BR0 = 65;                             // 8MHz 9600
        UCA0BR1 = 3;                              // 8MHz 9600
        UCA0MCTL|= UCBRS0;                        // Modulation UCBRSx = 1
        UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
        IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
}

void debug(unsigned int c)
{
  char i;
  #define z 34*8  // 28800
 
  P2OUT|=BIT2; //1
  __delay_cycles(z);
  P2OUT&=~BIT2; //0      //startt
  __delay_cycles(z);
  for (i=0;i<8;i++)
   {
    if (c & 1) P2OUT|=BIT2; //1
       else P2OUT&=~BIT2; //0
     c=c>>1;  
    __delay_cycles(z);
   }
  P2OUT|=BIT2; //1 stop
  __delay_cycles(104*8);

  P2OUT&=~BIT2; //0      //startt
  __delay_cycles(z);
  for (i=0;i<8;i++)
   {
    if (c & 1) P2OUT|=BIT2; //1
       else P2OUT&=~BIT2; //0
     c=c>>1;  
    __delay_cycles(z);
   }
  P2OUT|=BIT2; //1 stop
  __delay_cycles(104*8);
}

int command(char * str, unsigned int time, unsigned int patt)
{
  code=0;
  cnt_ch=0;
  timeout=time;
  pattern=patt;
  Send_UART(str); 
  while(timeout)
   {
    work_sens();
    if (pattern==0) return(1);
   }
  if (cnt_ch==0)
   {
     reset_modem();
     init_modem();
   } 
 return(0);
}


void rf_recal(void)         // рекалибровка радио
{
    TI_CC_SPISetup();
    TI_CC_On(); // инициализация радио
    TI_CC_SPIStrobe(TI_CCxxx0_SRX);  // перезапустим прием
    CLR_FL_CC;
}


void reset_modem(void)
{

   IE2 &= ~UCA0RXIE;         // Didable USCI_A0 RX interrupt
   P1SEL&=  ~(BIT1 + BIT2) ; // переключим в режим GPIO   // P1.1 = RXD, P1.2=TXD
   P1SEL2&= ~(BIT1 + BIT2) ; // переключим в режим GPIO   // P1.1 = RXD, P1.2=TXD
   UCA0CTL1=0;               // выключить UART
   P2OUT|=BIT1;              // выключить стабилизатор 3.9В
   P1OUT&=~BIT2;             // Port ноги TXD = 0;
   delay(3);// здесь пауза 3 сек
   P2OUT&=~BIT1;              // включить стабилизатор 3.9В
   init_uart();
   delay(3);
}


void init_modem(void)
{
   command("AT", 2, OK);
   command("AT", 2, OK);
   command("AT+CGDCONT=1,\"IP\",\"internet.beeline.ru\"",2,OK);
   command("AT#HTTPCFG=0",2,OK);
   command("AT#DTMF=0", 2, OK);
   command("AT+CLIP=0", 2, OK);
}


char http_send(void)
{
 int rez = 0;
 char httpstr[100];
 
 if (command("AT+CREG?", 2, REG))
  {  
    if (command("AT#SGACT?", 2,  ACT) == 0) command("AT#SGACT=1,1", 20, OK);
    if (command("AT#SGACT?", 2,  ACT) != 0)
     {
       delay(2);
       if (command("AT#SD=1,0,80,\"********.ru\"", 20, CONNECT))
       {
         delay(2);
         sprintf(httpstr,"GET /data_msg.php?temp=%d,%u,%u,%d,%u,%u,%u,%u, HTTP/1.0\r\nHost: ********.ru\r\n\r\n",tm1,imp1,bat1,tm2,imp2,bat2,pump,vent);
         cnt_s_pump=0;
         cnt_s_vent=0;
         rez = command(httpstr, 30, HTTPOK);
         delay(2);
         if (rez)
          {
            if (cnt_s_pump > 10) pump=(cnt_s_pump-10)*75;     // время полива в минутах * (0.75 сек * 75 = 60 сек)
            if (cnt_s_vent > 10) tON_vent=(cnt_s_vent-10)+20; // температура включения вентилятора
          }
       }
     } 
  }
  return(rez);
 
}


int main( void )
{
 
   WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

   BCSCTL1 = CALBC1_8MHZ;                    // Set DCO 8 MHz
   DCOCTL  = CALDCO_8MHZ;

   P2SEL=0; //отключим кварц

// запретим возможно использованную ранее в загрузчике периферию//////
   __disable_interrupt();  
   TA0CTL=0;
   TA1CTL=0;
   UCA0CTL1=0;
   UCB0CTL1=0;
   P1REN=0;
   P2REN=0;
/////////////////////////////////////////////////////////
 
   // это  для  "Telit" GL 868 dual
   // P1.0 - выход реле 1  (out, 0)
   // P1.1 - RX            (in)
   // P1.2 - TX            (out, 1)
  
   // P2.1 - reset модем   (out, 0) (при сбросе контроллера НЕ сбрасываем модем)
   // P2.2 - выход реле 2  (out, 0)
 
  
   P1OUT = 0x1E; // 0001 1110
   P1DIR = 0xBD; // 1011 1101 // биты 2,3,4 вывод единицы, бит 1 вход с подтяжкой к 1  - для RX, бит 1 - реле 1=0

   P1REN |= BIT6; // подтянем вход   MISO к земле    

   
   P2OUT = 0x50; // 0101 0000
   P2DIR = 0x57; // 0101 0111 // для cc1101 
  
/////////////////////////////////////////////////////////////////  

   BCSCTL3 |= LFXT1S_2;                // LFXT1 = VLO (ACLK) 
  
   IE1 |= WDTIE;                       // Enable WDT interrupt
   WDTCTL = WDT_ADLY_250;              // Set Watchdog Timer to exactly 0.75 s
   __enable_interrupt();

 
   tON_vent=T_ON;
   clear_data();      // обнуление данных
 
   rf_recal();
   init_uart();
   delay(3);
   init_modem();
 
  
//------------------------------------------------------------

  
   ///   MAIN LOOP  //////
   while (1)
    {
     
     if(http_send())  // посылка отправлена
      {
        rf_recal();     // здесь периодическая рекалибровка радио
        clear_data();   // обнуление данных после успешной посылки
        delay(INTERVAL);  // интервал * 0.75 сек.
      }
       else delay(2); // повторить попытку отправки через 1.5 сек.     
    }
 
}
//------------------------------------------------------------

#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
  if (timeout) timeout--;
  if (del_075) del_075--;
  if (pump){pump--;P1OUT|=BIT0;} // насос включен, если установлено время 
    else P1OUT&=~BIT0; // выключим насос после окончания времени    
  if (vent){vent--;P2OUT|=BIT2;} // вентилятор включен, если установлено время 
     else P2OUT&=~BIT2 // выключим вентилятор    
}


#pragma vector=USCIAB0RX_VECTOR
__interrupt void usart_interrupt(void)

{
  unsigned char ch;
  ch = UCA0RXBUF;
  cnt_ch++;
  if (ch!=0x0A)
   {
    if (ch==0x0D)
     {
      if (code !=0 )
      {
       //debug(code);
       if (code == pattern) pattern=0;    
       code=0;
      } 
     }
     else code=(code+ch);
    if(ch == '}') cnt_s_pump++; // считаем количество символов "}" в ответе PHP скрипта сервера
    if(ch == '{') cnt_s_vent++; // считаем количество символов "{" в ответе PHP скрипта сервера
   }
}

#pragma vector=NMI_VECTOR
__interrupt void nmi_interrupt(void)

{
  soft_reset();// пересброс 
 // ((void (*)())0x170)(); // Invalid fetch ("call #0170h") // пересброс
}