CRC (4 bits, calculated as dddd + nnnn + nnnn + nnnn truncated to 4 bits) Other infoWhen enabled (pin 3 held at 0V) the sensor will send the stream every 2 seconds.Complete stream 00100 dddd nnnn nnnn nnnn cccc, where d is direction, n is revolutions and c is CRC Velocity count appears somewhat nonlinear, the turbine is quite sensitive to small gusts below 4 knots. Knots = revolutions/8 (not sure of this i needs more detailed experiments)
I'm not responsible for this information, this information is provided has he is, it is not official it was reverse engineered!. Decoding the bit streamUsing IRQ - EXTINT0 PB25, J6 pin 25:
/*
* Driver for decoding WS2300-15 la crosse ANEMOMETER
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/gpio.h>
#include <asm/system.h>
#include <asm/arch/at32ap7000.h>
#include "chardev.h"
#define PORTB (void*)0xffe02C00
#define PIO_ISR 0x004c
#define PIN GPIO_PIN_PB(25)
#define PIN_IRQ gpio_to_irq(PIN)
int8_t dir;
unsigned int count;
const char str_dir[][5] = { "N","NNE","NE","ENE","E","ESE","SE","SSE",
"S","SSO","SO","OSO","O","ONO","NO","NNO" };
#define max_m 15 // number of values to average, 15 = 30 seconds
int8_t index=0;
int8_t m_dir[max_m];
unsigned int m_count[max_m];
int debug = 0;
module_param(debug,int,0);
//get averaged count value
int get_count(void)
{ int x; unsigned int tmp=0;
for (x=0;x<=max_m;x++)
{
tmp=tmp+m_count[x];
}
return (int)(tmp/max_m);
}
// get numerical direction
int get_ndir(void)
{ int x;
int count[15] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
int dir=0;
for (x=0;x<=max_m;x++)
{
count[m_dir[x]]++;
}
for (x=0;x<=15;x++)
{
if (count[x]>dir) dir=x;
}
return dir;
}
// get direction string
const char *get_dir(void)
{
return str_dir[get_ndir()];
}
// IRQ routine
static irqreturn_t read_stream(int irq, void *dev_id)
{
int u;
unsigned int acc=0;
unsigned int bn=0;
int8_t crc;
dir =0; count=0;
for(u=0; u<=24; u++)
{
udelay(600); // delaying inside irq is very bad, the system will "die" during delay ...
if(gpio_get_value(PIN)==0)
{ acc |= (1<
Using TIMER1 - Channel 0 , TIOB as TRIGGER PA25, J15 pin 17:
#include <linux/module.h>
#include <asm/io.h>
#include <asm/arch/portmux.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/clocksource.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/arch/time.h>
#include <asm/arch/at32ap7000.h>
#include <asm/gpio.h>
#include <asm/arch/board.h>
#include <asm/arch/portmux.h>
#define PORTA (void*)0xffe02800
#define PORTB (void*)0xFFE02C00
#define PIO_PER 0x0000
#define PIO_PDR 0x0004
#define ASR 0x0070
#define BSR 0x0074
#define PIO_OER 0x0010
#define PIO_SODR 0x0030
#define PIO_CODR 0x0034
#define PM (void*)0xfff00000
#define PWM_BASE (void*)0xfff01400
#define TC1_BASE (void*)0xfff01000
#define PBBMASK_OFFSET 0x14
#define PWM_CLK_EN_BIT 5
#define TC1_CLK_EN_BIT 4
#define CCR_OFFSET 0x00
#define CMR_OFFSET 0x04
#define CV_OFFSET 0x10
#define RA_OFFSET 0x14
#define RB_OFFSET 0x18
#define RC_OFFSET 0x1C
#define SR_OFFSET 0x20
#define IRQ_ENA_OFFSET 0x24
#define IRQ_DIS_OFFSET 0x28
#define IMR_OFFSET 0x28
#define CMR0_OFFSET 0x200
#define CPRD0_OFFSET 0x208
#define CDTY0_OFFSET 0x204
#define PWM_ENA_OFFSET 0x4
#define PWM_DIS_OFFSET 0x8
#define CLOCK_SOFT_TRIGGER __raw_writel(5, TC1_BASE + CCR_OFFSET)
#define IN_PIN GPIO_PIN_PA(25)
static int bit_count = 0;
static ulong stream =0;
static irqreturn_t timer_int(int irq, void *dev_id)
{ unsigned long mode;
if(gpio_get_value(IN_PIN)==0)
stream |= (1<< bit_count);
if (bit_count==0)
{
__raw_writel((1 << 4 ), TC1_BASE + IRQ_ENA_OFFSET);
mode = (1 << 2) | 1 << 14 | 1 << 15; // disable ext trigger int
__raw_writel(mode, TC1_BASE + CMR_OFFSET);
}
if (bit_count==1)
__raw_writel(0X9C0, TC1_BASE + RC_OFFSET); // load RC
if (bit_count==24)
{ // stream ended, prepare for new stream and set ext trigger
__raw_writel(2, TC1_BASE + CCR_OFFSET); // stop counter
mode = (1 << 2) | 1 << 8| 1 << 12| 1 << 14 | 1 << 15;
__raw_writel(mode, TC1_BASE + CMR_OFFSET); // define ext trigger start
__raw_writel(( 1 << 7 )|(1 << 4 ), TC1_BASE + IRQ_ENA_OFFSET); // irq masq
__raw_writel(0XF00, TC1_BASE + RC_OFFSET); // load RC
__raw_writel(1, TC1_BASE + CCR_OFFSET); // enable counter
bit_count=0;
printk("Stream: %lu",stream); stream=0;
__raw_readl(TC1_BASE + SR_OFFSET); // clear irq flag
return IRQ_HANDLED;
}
bit_count++;
__raw_readl(TC1_BASE + SR_OFFSET); // clear irq flag
return IRQ_HANDLED;
}
void tc1_enable(void)
{ u32 mask;
mask = __raw_readl(PM+PBBMASK_OFFSET);
mask |= 1 << TC1_CLK_EN_BIT;
__raw_writel(mask, PM+PBBMASK_OFFSET);
}
void tc1_disable(void)
{ u32 mask;
mask = __raw_readl(PM+PBBMASK_OFFSET);
mask &= ~(1 << TC1_CLK_EN_BIT);
__raw_writel(mask, PM+PBBMASK_OFFSET );
}
int init_module(void)
{ unsigned long u,mode;
int res;
__raw_writel( (1 << 25) , PORTA + PIO_PDR); // periferico
__raw_writel( (1 << 25) , PORTA + BSR); // periferico B
res = gpio_direction_input(IN_PIN);
if (res < 0) {
printk(KERN_ALERT "could not set gpio direction: %d\n", IN_PIN);
gpio_free(IN_PIN);
return res;
}
res = request_irq(23, timer_int, 0, "atmel_timer", NULL);
if (res) {
printk (KERN_ALERT "Error request_irq");
return res;
}
tc1_enable();
/* TC1 section */
/* CLK is TIMER_CLOCK5, ie, PBB_CLK/32 */
mode = (1 << 2) | 1 << 8| 1 << 12| 1 << 14 | 1 << 15;
__raw_writel(mode, TC1_BASE + CMR_OFFSET);
__raw_writel(0XF00, TC1_BASE + RC_OFFSET); // load RC
// enable irq on, compare and extint on TIOB0
__raw_writel(( 1 << 7 )|(1 << 4 ), TC1_BASE + IRQ_ENA_OFFSET);
/* enable TC1 unit */
__raw_writel(1, TC1_BASE + CCR_OFFSET);
return 0;
}
void cleanup_module(void)
{
__raw_writel(2, TC1_BASE + CCR_OFFSET); // stop timer
__raw_writel(255, TC1_BASE + IRQ_DIS_OFFSET); // disable timer...
tc1_disable(); // disable timer clock ...
free_irq(23, NULL);
}
MODULE_AUTHOR("Carlos Ribeiro");
MODULE_DESCRIPTION("WS2300-15 Stream Decode using TIMER1 chanel 0, TIOB as Trigger");
MODULE_LICENSE("GPL");
Results
Samples every 30 seconds averaged to 1 minute, Gust on last 5 min. Live Linkhttp://coisas.mine.nu/cgi-bin/ws2300 6 visitor(s) this week :
|
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries. Atmel®, AVR® and others are registered trademarks or trademarks of Atmel Corporation or its subsidiaries. All other trademarks are the property of their respective owners. |
|||||||||||||||||||||||||||||||||||||