/Designs/Measuring_instruments/AWS01B/SW/PIC16F887/i2c_wind_sensor/README.cs.txt
1,12 → 1,8
I2C snimac vycitajici rychlost větru a srážky.
 
 
 
 
 
===== Měření srážek =====
 
V MCU je čítač použitý pro počítání překlopení člunku ve srážkoměru. Je ošetřeno jeho přetečení tak, aby mohl čítat z hlediska srážek až do velkých čísel. Tento čítač se nenuluje, ale nechává se přetéct. K němu paralelně běží RTC hodiny v MCU. A MCU se chová jako I²C SLAVE a hodnotu čítače tak lze vyčíst přes I2C.
MCU pak ve zbytku výpočetního času kontroluje hodnotu čítače a do dalšího registu zapisuje čas jeho poslední změny ve formátu Unix time stamp.
 
RTC hodiny MCU mohou být nastavovány buď přes GPS. (Zprávou NMEA) A nebo zápisem do registru obsahujícího aktuální čas. Tento registr může být použit jako zdroj korekce v případě komplikací s nastavením aktuálního času.
V MCU je čítač použitý pro počítání překlopení člunku ve srážkoměru. Je ošetřeno jeho přetečení tak, aby mohl čítat z hlediska srážek až do velkých čísel. Tento čítač se nenuluje, ale nechává se přetéct. K němu paralelně běží uptimo hodiny v MCU. A MCU se chová jako I²C SLAVE a hodnotu čítače tak lze vyčíst přes I2C.
MCU pak ve zbytku výpočetního času kontroluje hodnotu čítače a do dalšího registu zapisuje čas jeho poslední změny. (podobne jako dmesg, ale zaokrouhleno na cele sekundy)
Uptime bude zaznamenavan do registru, ktere je mozne precist pres I2C. Tento registr může být použit jako zdroj korekce v případě komplikací s nastavením aktuálního času.
/Designs/Measuring_instruments/AWS01B/SW/PIC16F887/i2c_wind_sensor/main.c
1,72 → 1,212
#define VERSION "0.1"
#define ID "$Id: main.c 2916 2013-04-14 17:42:03Z kaklik $"
 
#include "main.h"
#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,force_hw,address=0xA2) // Motor 2
#use i2c(SLAVE,Fast,sda=PIN_C4,scl=PIN_C3,force_hw,address=0xA2) // Motor 2
 
#define H1 PIN_A1
#define L1 PIN_A2
#define H2 PIN_A3
#define L2 PIN_A4
#include <time.h> //standard C time library
#include <rtctimer.c> //library for time.h that uses timer2 as time base
 
signed int8 command; // rozsah +-127
#include <stdlib.h>
#include <input.c> //needed for the rs232 input routines
 
 
int16 count=0xA5A5;
const int8 buf_len=8;
 
int8 buffer[buf_len]; // I2C buffer
 
int8 address=0;
 
#include "..\common\dbloader.h"
 
unsigned int16 timer0_overflow_count;
float anemo=0;
unsigned int8 rain;
 
//we are using the rtctimer.c library, in which a counter is incremented
//every time the timer2 interrupt occurs (timer2 overflow). the time math
//needs to know what rate the timer2 interrupt occurs. this definition
//must match the rate the timer2 is configured for.
#define CLOCKS_PER_SECOND 1000
 
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
BYTE incoming, state;
 
output_a(0); // vypnuti vsech budicu
 
state = i2c_isr_state();
 
if(state < 0x80) //Master is sending data
{
command = i2c_read();
incoming = i2c_read();
if(state == 1) //First received byte is address
{
address = incoming;
if (incoming == 2)
{
buffer[0]=make8(count,0);
buffer[1]=make8(count,1);
}
}
if(state == 2) //Second received byte is data
buffer[address] = incoming;
}
 
if(state == 0x80) //Master is requesting data
{
i2c_write(command);
if(address <= buf_len) i2c_write(buffer[address]);
else i2c_write(ID[address - buf_len]);
}
}
 
#int_TIMER1
void TIMER1_isr(void)
{
// 32.768 kHz krystal pro timer1 oscilátor
anemo = ((timer0_overflow_count * 0xFF) + get_timer0())/(0xFFFF/32768.0); // pocet pulzu za 1s
 
timer0_overflow_count=0; //nulovani
set_timer0(0);
set_timer1(0);
output_toggle(PIN_E0);
}
 
#int_TIMER0 //pro preteceni \u010díta\u010de p\u016flz\u016f od anemometru (RA4)
void TIMER0_isr(void)
{
timer0_overflow_count++;
}
 
#INT_EXT
void EXT_isr() //interrup from rain sensor clip.
{
rain++;
// if (input(PIN_B0)) ext_int_edge( H_TO_L ); osetreni pro pripad, ze by bylo treba cist obe hrany impulzu
// if (!input(PIN_B0)) ext_int_edge( L_TO_H );
}
 
 
void welcome(void) // uvodni zprava
{
printf("\r\n\r\n# Meteorologicka stanice %s (C) 2013 www.mlab.cz \r\n",VERSION);
printf("\r\n %s \r\n",ID);// Welcome message
printf("# ver poradi ");
printf("check\r\n\r\n");
}
 
void InitTime(void)
{
struct_tm t;
//tm_year is years since 1900.
printf("\r\nYear (0-99): ");
t.tm_year = (int16)get_int() + (int16)100; //add 100 to put is into 2000
printf("\r\nMonth (1-12): ");
t.tm_mon = get_int() - 1;
printf("\r\nDay (1-31): ");
t.tm_mday = get_int() - 1;
printf("\r\nHour (0-23): ");
t.tm_hour = get_int();
printf("\r\nMinute (0-59): ");
t.tm_min = get_int();
SetTime(&t);
printf("\r\n\n");
}
 
 
void main()
{
int8 speed;
 
char tString[32];
unsigned int32 t;
time_t tTime = 0;
 
 
setup_adc_ports(NO_ANALOGS|VSS_VDD);
// setup_adc(ADC_CLOCK_DIV_2);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL);setup_wdt(WDT_144MS);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
// setup_spi(SPI_SS_DISABLED); //must not be set if I2C are in use!
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1);
// setup_timer_0(RTCC_INTERNAL);setup_wdt(WDT_144MS);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);
// setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);
// setup_oscillator(OSC_8MHZ|OSC_INTRC);
 
 
InitTime();
 
/* Setup timer 2
* On a 4 Mhz clock, this will trigger a timer2 interrupt every 1.0 ms
* For time.h to work properly, Timer2 must overflow every millisecond
* OverflowTime = 4 * (1/OscFrequency) * Prescale * Period * Postscale
* For 4 Mhz: .001 seconds = 4 * (1/4000000 seconds) * 4 * 250 * 1
*/
#if getenv("CLOCK")==4000000)
setup_timer_2(T2_DIV_BY_1,250,4);
#elif getenv("CLOCK")==20000000)
setup_timer_2(T2_DIV_BY_4,250,5);
#else
#error Configure TIMER2 so it interrupts at a rate defined by CLOCKS_PER_SECOND
#endif
/* Enable the timer 2 interrupt, or it will not fire */
enable_interrupts(INT_TIMER2);
/* Enable interrupts globally too, otherwise no interrupt will fire */
 
 
 
enable_interrupts(INT_SSP);
// enable_interrupts(INT_TIMER2);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
 
command=-128; // zastaveni po resetu
 
set_timer0(0);
set_timer1(0);
timer0_overflow_count=0;
rain=0;
 
buffer[2]=0;
buffer[3]=0;
buffer[4]=0;
buffer[5]=0;
 
 
welcome();
 
set_timer1(0);
 
while(true)
{
set_timer1(0);
delay_ms(999);
delay_us(966);
// count=get_timer1();
// Get the time
tTime = time(NULL);
// Get the string representation of the time */
 
if (command==-128) // prikaz na odpojeni mustku nebo chybna hodnota
{
output_a(0); // volnobeh
continue;
};
ctime(&tTime, tString);
 
speed=command+127; // posunuti 0 pro zaporna cisla
/* Print the time to RS-232 */
printf("Time: %s\n\r", tString);
 
output_a(0b10010); // vpred
delay_us(speed);
output_a(0); // vypnuti vsech budicu
delay_us(1);
restart_wdt();
output_a(0b01100); // vzad
delay_us(254-speed);
output_a(0); // vypnuti vsech budicu
delay_us(1);
printf("count: %Lu %X %X %X %X\r\n",count, buffer[0],buffer[1],buffer[2],buffer[3]);
printf("%6.1f %u \n\r", anemo, rain);
delay_ms(1000);
 
}
}
 
/Designs/Measuring_instruments/AWS01B/SW/PIC16F887/i2c_wind_sensor/main.h
5,7 → 5,7
 
//#FUSES WDT // Watch Dog Timer
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc
#FUSES HS //external crystal oscillator
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
18,10 → 18,10
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brownout reset at 4.0V
 
#use delay(clock=8000000)
#use delay(clock=20000000)
 
//set I2C
//#use i2c(Master,Slow,sda=PIN_C4,scl=PIN_C3)
 
//set RS232
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)