Android手机+蓝牙扩展电路=示波器
Android系统的手机是智能手机家族里面的新宠,而且大有成为龙头老大之势。开发人员纷纷投身Android,开发了很多精彩的应用。
下面就介绍一个比较新奇的应用。它利用一块dsPIC电路采集信号,处理后通过蓝牙发送给Android系统上的程序,将手机变身为简易示波器。
挺不错! 这个好啊,不知性能如何,价格如何 前排关注MARK 早看過。 老大呀 !速度! 不错哈,支持下 芯片内部2*2M的ADC 不知道有没有现货。 不知道性能怎么样? 蓝牙模块不知道可以买到不? 不错,不过手机屏幕小拉点,平板上应该不错 简单用用应该还是不错滴
有换手机的冲动了 想法好,实用性如何? 兄弟们,开搞啊
如果一直在示波器上浪费时间,那你的一生都浪费在所谓的示波器上,而你搞两辈子也搞不过泰克安捷伦的,所以省省吧。 花几条烟钱就可以买个完备的示波器了。 manhere 发表于 2012-5-4 09:19 static/image/common/back.gif
不知道性能怎么样?
估计简易的就那样 本帖最后由 kejiren123 于 2012-5-15 10:10 编辑
强烈建议logicgreen 大移植到LGT单片机上,如果能出套件相信很多人会买。我愿意出100元买一个LGT单片机的示波器套件(预估材料成本在40-60元)。
我看了,代码不复杂。以下为全部源码。
************************************
Bluetooth Oscilloscope
yus - projectproto.blogspot.com
September 2010
*************************************/
#include "main.h"
_FOSCSEL(FNOSC_FRC); // Select Internal FRC at POR
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF); // Enable Clock Switching and Configure
_FICD(ICS_PGD1 & JTAGEN_OFF);
int main(void)
{
unsigned char c;
osc_init();
port_init();
ser_init();
adc_init();
timer1_init();
//initial values;
ch1_position = 120;
ch2_position = 120;
ch1_gain = VOLT_PER_DIV;
ch2_gain = VOLT_PER_DIV;
while(1)
{
if(ser_isrx()){
led_off();
c = ser_getch(); //get 1 character from receive buffer
switch(c){
case REQ_DATA:
store_raw_data();
ser_putch(DATA_START);
send_data();
ser_putch(DATA_END);
break;
case ADJ_HORIZONTAL:
c = ser_getch();
if( (c<13) ){ // refer to "timer.h"
set_sampling_period( PERIODS );
}
break;
case ADJ_VERTICAL:
c = ser_getch(); // refer to "adc.h"
if(c==CHANNEL1) ch1_gain = VOLT_PER_DIV;
else if(c==CHANNEL2) ch2_gain = VOLT_PER_DIV;
break;
case ADJ_POSITION:
c = ser_getch();
if(c==CHANNEL1) ch1_position = (long)ser_getch() * 6;
else if(c==CHANNEL2) ch2_position = (long)ser_getch() * 6;
break;
default:
break;
} // switch(command)
led_on();
}//if-ser_isrx()
}//while-true
}
void osc_init(void)
{
// Configure PLL prescaler, PLL postscaler, PLL divisor
PLLFBD = 41; // M = 43
CLKDIVbits.PLLPOST=0; // N1 = 2
CLKDIVbits.PLLPRE=0; // N2 = 2
// Initiate Clock Switch to Internal FRC with PLL (NOSC = 0b001)
__builtin_write_OSCCONH(0x01);
__builtin_write_OSCCONL(0x01);
// Wait for Clock switch to occur
while (OSCCONbits.COSC != 0b001);
// Wait for PLL to lock
while(OSCCONbits.LOCK!=1) {};
}
void port_init(void)
{
// LED Pin Configuration:I/O Port RC3; pin 5
PORTCbits.RC3 = 0; // Configure as Output
TRISCbits.TRISC3 = 0; // Configure as Output
LATCbits.LATC3 = 1; // Initialize to zero
RPINR18bits.U1RXR = 28; //RX -> pin 20 (RP28)
RPOR13bits.RP27R = 0b00011; //TX -> pin 19 (RP27)
ADPCFGbits.PCFG4 = 0; // AN4 is configured as analog input
ADPCFGbits.PCFG5 = 0; // AN5 is configured as analog input
}
void send_data(void)
{
#define bits 10
unsigned int i, total;
unsigned int repeat, n;
unsigned char plot_data1, plot_data2;
signed long temp;
total = get_total_samples();
repeat = MAX_SAMPLES / total;
i=0;
while( i<total )
{
/** refer to "adc.xmcd" (mathcad) for the computation
** "zero level" is on Vref/2**/
// CHANNEL 1
temp = (ch1_position<<bits) / (long)MAX_LEVEL;
temp = (long)OFFSET1 + temp - (long)raw_data;
temp = temp * (long)MAX_LEVEL * ch1_gain;
temp = (temp>>bits) + (ch1_position<<2) - (ch1_position*ch1_gain);
temp = temp>>2;
plot_data1 = clamp_value( temp );
// CHANNEL 2
temp = (ch2_position<<bits) / (long)MAX_LEVEL;
temp = (long)OFFSET2 + temp - (long)raw_data;
temp = temp * (long)MAX_LEVEL * ch2_gain;
temp = (temp>>bits) + (ch2_position<<2) - (ch2_position*ch2_gain);
temp = temp>>2;
plot_data2 = clamp_value( temp );
n=repeat;
while(n--){
ser_putch( plot_data1 );
ser_putch( plot_data2 );
}
}
}
unsigned char clamp_value(long value)
{
if(value<0)
return 0;
else if (value>(long)MAX_LEVEL)
return ((unsigned char) MAX_LEVEL);
else
return (unsigned char) value;
}
***********************************************************************************************************************************************
#include "p33fxxxx.h"
#include "adc.h"
#include "timer.h"
volatile unsigned int adc_value_1;
volatile unsigned int adc_value_2;
volatile unsigned int raw_data;
volatile unsigned int samples_count;
const long VOLT_PER_DIV[]={
SCALE_10mV,
SCALE_20mV,
SCALE_50mV,
SCALE_100mV,
SCALE_200mV,
SCALE_500mV,
SCALE_1V,
SCALE_2V,
SCALE_GND
};
void adc_init(void)
{
ADCONbits.ADON = 0; // Temporarily Turn off ADC to allow for initialization settings
aux_pll_init();
ADCONbits.FORM = 0; // Output in Integer Format
ADCONbits.EIE = 1; // Enable Early Interrupt (7TAD)
//ADCONbits.ORDER = 0; // Normal Order of conversion
//ADCONbits.SEQSAMP = 0; // Simultaneous sampling
ADCONbits.ASYNCSAMP = 1; // Asynchronous sampling
ADCONbits.SLOWCLK = 0; // High Frequency Clock input (use aux pll)
ADCONbits.ADCS = 0; //5; // Clock divider selection
ADCPC1bits.TRGSRC2 = 0b01100; // Timer1 period match (trigger source)
ADPCFGbits.PCFG4 = 0; // AN4 is configured as analog input
ADPCFGbits.PCFG5 = 0; // AN5 is configured as analog input
IPC28bits.ADCP2IP = 0x01; // Set ADC Pair 2 Interrupt Priority (Level 1)
IFS7bits.ADCP2IF = 0; // Clear ADC Pair 2 Interrupt Flag
//IEC7bits.ADCP2IE = 1; // Enable ADC Pair 2 Interrupt
ADCONbits.ADON = 1; // Enable ADC module
}
/* ADC Pair 2 ISR*/
void __attribute__((interrupt, no_auto_psv)) _ADCP2Interrupt (void)
{
raw_data = ADCBUF4; // Read AN4 conversion result;
raw_data = ADCBUF5; // Read AN5 conversion result;
IFS7bits.ADCP2IF = 0; // Clear ADC Pair 2 Interrupt Flag
}
void store_raw_data(void)
{
unsigned int total_samples;
total_samples = get_total_samples();
samples_count = 0; // reset counter
//IEC0bits.U1RXIE = 0; // disable RX interrupt
IEC7bits.ADCP2IE = 1; // enable ADC Pair 2 Interrupt
TMR1 = 0x0000; // reset timer 1
T1CONbits.TON = 1; // Starts 16-bit Timer1
while(samples_count<total_samples); // wait until samples are completed
IEC7bits.ADCP2IE = 0; // disable ADC Pair 2 Interrupt
T1CONbits.TON = 0; // Stops 16-bit Timer1
//IEC0bits.U1RXIE = 1; // Enable RX interrupt
}
unsigned int get_total_samples(void)
{
if(sampling_period==PERIOD_5us)
return (MAX_SAMPLES/4);
else if(sampling_period==PERIOD_10us)
return (MAX_SAMPLES/2);
else
return (MAX_SAMPLES);
}
void aux_pll_init(void)
{
ACLKCONbits.FRCSEL = 1; // Internal FRC is clock source for auxiliary PLL
ACLKCONbits.ENAPLL = 1; // APLL is enabled
ACLKCONbits.SELACLK = 1; // Auxiliary PLL provides the source clock for the clock divider
ACLKCONbits.APSTSCLR = 7; // Auxiliary Clock Output Divider is Divide by 1
while(ACLKCONbits.APLLCK != 1){}; // Wait for Auxiliary PLL to Lock
}
***********************************************************************************************************************************************
#define _SER_C_
#include "p33fxxxx.h"
#include "ser.h"
unsigned char txfifo;
volatile unsigned char txiptr, txoptr;
unsigned char rxfifo;
volatile unsigned char rxiptr, rxoptr;
unsigned char ser_tmp;
void ser_init(void)
{
//RPINR18bits.U1RXR = 28; //RX -> pin 20 (RP28)
//RPOR13bits.RP27R = 0b00011; //TX -> pin 19 (RP27)
U1MODEbits.STSEL = 0; // 1-stop bit
U1MODEbits.PDSEL = 0; // No Parity, 8-data bits
U1MODEbits.ABAUD = 0; // Auto-Baud Disabled
U1MODEbits.BRGH = 1; //High-Speed mode
U1BRG = BRGVAL; // BAUD Rate Setting
U1STAbits.UTXISEL0 = 0; // Interrupt after one Tx character is transmitted
U1STAbits.UTXISEL1 = 0;
U1STAbits.URXISEL = 0b00; // Interrupt after one RX character is received;
IEC0bits.U1RXIE = 1; //Enable RX interrupt
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXEN = 1; // Enable UART Tx
//set ring pointers to empty (zero receive/transmit)
rxiptr=rxoptr=txiptr=txoptr=0;
}
void ser_putch(unsigned char byte)
{
// wait until buffer has an empty slot.
//while (((txiptr+1) & SER_FIFO_MASK)==txoptr)
while (U1STAbits.UTXBF)
continue;
txfifo = byte; //place character in buffer
//increase ring input pointer and set it to zer0 if
//it has rolled-it over.
txiptr=(txiptr+1) & SER_FIFO_MASK;
IEC0bits.U1TXIE = 1; //enable interrupt driven
//serial transmission
}
void ser_puts(unsigned char * s)
{
while(*s) //while pointer s is not at end of string
ser_putch(*s++); // send the current character,
// then increment pointer
}
void ser_puthex(unsigned char v)
{
unsigned char c; //define temp variable
c = v >> 4; //get the high nibble and place it in c
if (c>9) { //if more than 9
ser_putch('A'-10+c); // send the difference from 10 + 'A'
} else { //else
ser_putch('0'+c); // send '0' + the high nibble
}
c = v & 0x0F; //get the lower nibble
if (c>9) { //process the character
ser_putch('A'-10+c); //and send it same as above
} else { //
ser_putch('0'+c); //
}
}
unsigned char ser_isrx(void)
{
if(U1STAbits.OERR) //error in reception?
{
U1STAbits.OERR = 0; //must clear the overrun error to keep uart receiving
return 0; // return no characters in buffer
}
return (rxiptr!=rxoptr); //checks buffer if char is present
}
unsigned char ser_getch(void)
{
unsigned char c; //define
while (ser_isrx()==0) //wait until a character is present
continue; //
c=rxfifo; //get oldest character received
++rxoptr; //move the pointer to discard buffer
rxoptr &= SER_FIFO_MASK; //if the pointer is at end, roll-it over.
return c; //return it
}
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
{
U1TXREG = txfifo;
++txoptr;
txoptr &= SER_FIFO_MASK;
if (txoptr==txiptr) IEC0bits.U1TXIE = 0;
}
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{
rxfifo=U1RXREG;
ser_tmp=(rxiptr+1) & SER_FIFO_MASK;
if (ser_tmp!=rxoptr) rxiptr=ser_tmp;
IFS0bits.U1RXIF = 0;
}
***********************************************************************************************************************************************
#include "p33fxxxx.h"
#include "timer.h"
volatile unsigned int sampling_period;
const unsigned int PERIODS[]={
PERIOD_5us,
PERIOD_10us,
PERIOD_20us,
PERIOD_50us,
PERIOD_100us,
PERIOD_200us,
PERIOD_500us,
PERIOD_1ms,
PERIOD_2ms,
PERIOD_5ms,
PERIOD_10ms,
PERIOD_20ms,
PERIOD_50ms
};
void timer1_init(void)
{
T1CONbits.TON = 0; // Stops 16-bit Timer1
T1CONbits.TCKPS = 0b00; // Timer1 Input Clock Prescale Select bits
T1CONbits.TCS = 0; // Internal clock (FCY)
T1CONbits.TGATE = 0; // Gated time accumulation disabled
set_sampling_period(PERIOD_200us);
//T1CONbits.TON = 1; // Starts 16-bit Timer1
}
void set_sampling_period(unsigned int period)
{
#if 0
PR1 = period;
#else // adc speed limitation
if( (period==PERIOD_5us) || (period==PERIOD_10us) )
PR1 = PERIOD_20us;
else
PR1 = period;
#endif
sampling_period = period;
}
csdnct 发表于 2012-5-4 13:32 static/image/common/back.gif
如果一直在示波器上浪费时间,那你的一生都浪费在所谓的示波器上,而你搞两辈子也搞不过泰克安捷伦的,所以 ...
说的是,这玩意没多大意思。 蓝牙,速度能有多快?
dspic标称的AD不过是1MSPS的样子。关键还是安卓设备上的编程。 期待套件 采样率能达到多少?带宽呢?
安卓上的软件呢? 电子电路网有全部的下载 关注一下。。。。 蓝牙串口模块+单片机? mark{:biggrin:} kejiren123
你的头像是av明星吗?我好想看一下啊.
如果是你女朋友,真的好羡慕你啊. bywqdq123 发表于 2012-7-8 12:16 static/image/common/back.gif
kejiren123
你的头像是av明星吗?我好想看一下啊.
如果是你女朋友,真的好羡慕你啊. ...
这个头像应该是网络红人妮妮的自拍照请看链接 http://www.kuaikuaiyouxi.com/game-59047.html
妮妮又叫台湾妮妮,也人称台湾美女妮妮、网络美女妮妮,台湾妮妮、台湾美女妮妮、网络美女妮妮自从上传了自己的照片,一举成了网络红人。其实她本人更喜欢让别人叫妮妮,什么台湾妮妮,台湾美女妮妮、网络美女妮妮,这样的称呼让她很不习惯。
http://www.kuaikuaiyouxi.com/upload/20112822/20110611082901234.jpg
妮妮的姓名:刘孟姗
昵称: 妮妮
性别:女
生日:1988年8月13日
星座:狮子座
血型:AB型
身高: 163cm
体重:43kg
婚姻状况:未婚
妮妮讨厌的人:没素质,鸡婆,爱管别人闲事,造谣生事,小题大做的人
妮妮喜欢做的事:看好看的书、过简单的生活、逗我家的狗狗、发呆 ,看帅哥,靓女(养眼)
妮妮讨厌做的事:讨厌妈妈逼我吃不爱吃的东西(说有营养) 讨厌被别人讨厌 -
妮妮最大的优点:有毅力,万事都看的开,不记仇,再大的仇恨睡一觉起来就忘记了妮妮最大的缺点:说话太直,得罪人,粗心,爱丢三落四,太冷,对很多人和事都没兴趣-
妮妮最喜欢的颜色:白,紫,粉,蓝
妮妮喜欢的地方:郊外,开满鲜花的地方,安静,没有喧嚣的地方
妮妮最喜欢的衣服:学生装,淑女装,都市时尚装扮
妮妮最喜欢的歌曲:说唱,嗨歌,舞曲,及所有的伤感音乐
台湾妮妮玩自己在台湾无名的部落格,经常在那里上传自己的照片然后人气就上来了也就红了。
台湾妮妮,鬼故事nj,从事有声鬼故事创作,其最早是在校学生,兼职45°网络广播电台,播音主持。其作品以各种鬼故事为题材,进行有声创作,其中以长篇故事见长。选材偏重情感,经典代表作有长篇有声鬼故事《幽冥三部曲之冤鬼路》、《幽冥三部曲之樱花厉魂》、《幽冥三部曲之灵堂课室》、《戒指》、《恐怖的203室》、《鬼童》等等。2006年底,台湾妮妮因继续学业而暂时离开了喜爱她的听众们。 好像头像那一张更清纯一下,给人浅见.
谢谢keshipt资料找的这么全.
求蓝牙示波器 请教高手,我台MOTO MB860 安装后找不到图标,是不是只适合三星机? mark出的话我省吃俭用都要买~~~换手机~~虽然我只是个学生~~~~~ manhere 发表于 2012-5-4 09:19 static/image/common/back.gif
不知道性能怎么样?
同关心~~~ 这个很强大! 我们的PIC单片机已经到位,PCB正在绘制中,还找了一个软件工程师加入,做出样品问题应该不大。 mark牛人 kejiren123 发表于 2012-7-18 23:16 static/image/common/back.gif
我们的PIC单片机已经到位,PCB正在绘制中,还找了一个软件工程师加入,做出样品问题应该不大。 ...
看了你不仅仅是头像给力啊 不知道在其他安卓智能机上能不能用,能用的话我做个PCB,硬件应该不难
用手机屏太小,最好用平板。现在安卓的平板挺多的。 Hunter 发表于 2012-5-4 09:43 static/image/common/back.gif
蓝牙模块不知道可以买到不?
蓝牙模块能买到哦程序下载了 也能跑 但是源代码好像有点问题呢。我下载下下来编译不出啦。 如果蓝牙速度不够,也可以用Wifi,要是对测试结果有疑问,还方便求助,配合PC客户端或者Web界面,整个局域网都可以访问{:victory:} 关注实用性,呵呵,实用性好就量产开公司可以了 支持,出套件的话准备入手一套 手机也不错啊,但是pic单片机玩的人不多最好能一直到别的单片上面去 stm avr 好东西 必须顶 谢谢分享!!!!!!!!!!! 谢谢楼主分享 {:sad:}围观群众+! 竟然有源代码 哈哈哈 goodman
mark.手机看帖咋没收藏功能呢 bywqdq123 发表于 2012-7-8 12:16 static/image/common/back.gif
kejiren123
你的头像是av明星吗?我好想看一下啊.
如果是你女朋友,真的好羡慕你啊. ...
只能说哪里都有亮点。 好东西,mark! 这栋栋绝对是个好玩儿的主! 高人实在是高,可惜真心看不懂啊 不错有时间我也做一个! 这个很棒,绝对有搞头,电子工程师基本都是4寸屏的手机吧, 要是外带一个火柴盒大小的采样模组,在哪里都可以开工干活了。{:smile:} 看起来很不错,有机会试试搞一个 没有后续了吗
{:sweat:}{:sweat:} mark,Android手机+蓝牙扩展电路=示波器。 说好的套件呢? 说好的套件呢? csdnct 发表于 2012-5-4 13:32
如果一直在示波器上浪费时间,那你的一生都浪费在所谓的示波器上,而你搞两辈子也搞不过泰克安捷伦的,所以 ...
人家只是研究,并没有说要和谁比,支持楼主的想法,我也有过这样的想法,只是行动力不够了 这个示波器好像也是基于蓝牙串口的哦 要是知道协议可以自己做硬件 就爽了 实际还是挺不错的 比如显示电池电压什么的应该很好 很好的资料,先收藏了
页:
[1]