1 Arduino蓝牙低能耗跳伞高度计-德赢Vwin官网 网
×

Arduino蓝牙低能耗跳伞高度计

消耗积分:0 | 格式:zip | 大小:0.32 MB | 2023-07-05

分享资料个

描述

背景:

我正在寻找一个跳伞数字高度计,发现它们在这里的价格约为 300 到 500 美元不仅如此,它们中的大多数都具有三个按钮,但它们在每个设备上执行的功能并不相同。因此,我们必须阅读手册并记住每个功能的按钮按下顺序。

在本教程中,我们将大量提及Audible Abby ,因此,熟悉该项目会有所帮助。我收到的关于 Audible Abby 的反馈之一是“那么,您如何更改警报高度?”。老实说,如果你不了解 Arduino,那你就不走运了!

上述问题的解决方案是一个免费的 Android 蓝牙低功耗 (BLE) 应用程序,它允许您使用智能手机调整飞机的高度。启动后,该应用程序会连接到由安森美半导体的 RSL10-SENSE-DB-GEVK 提供支持的自制高度计 (ALTER)。

本教程的目的是教你如何钓鱼,而不是仅仅看着我吃生鱼片。您将学习如何进行恢复出厂设置、创建 BLE Android 应用程序、将 OLED 添加到您的项目中、从 RSL10-SENSE-DB-GEVK 中获取更多 GPIO,以及应对生活中的逆境。

一路走来,我会尽我所能来招待你,因为这将是一个很长的教程;所以,你可能想坐下。如果您已经坐下,则无需采取进一步行动。

软件:没有 ALTER 就无法拼写高度计

这一步可能看起来很吓人,但是一旦你知道了几件事,它就真的很简单了。Martyn Currey的教程展示了如何轻松创建免费的 Android 应用程序以将您的手机连接到 BLE 设备。这里的问题是 UUID 看起来像这样:

0000FFE0-0000-1000-8000-00805F9B34FB

如果您打开 BLE_ICS.h(在 Pack 文件夹中),您会看到如下内容:

#define ICS_SERVICE_UUID { 0x24, 0xdc, 0x0e, 0x6e, 0x01, 0x40, \ 0xca, 0x9e, 0xe5, 0xa9, 0xa3, 0x00, \ 0xb5, 0xf3, 0x93, 0xe0 }

以下是如何将您的格式转换为ai2.appinventor.mit.edu可用的格式

1 - 保留空格并删除花括号、逗号和 0x 24 dc 0e 6e 01 40 ca 9e e5 a9 a3 00 b5 f3 93 e0

2 - 反转所有对的顺序(第一对变为最后,最后一对变为第一) e0 93 f3 b5 00 a3 a9 e5 9e ca 40 01 6e 0e dc 24

3 - 删除空格 e093f3b500a3a9e59eca40016e0edc24

4 - 添加四个战略破折号 e093f3b5-00a3-a9e5-9eca-40016e0edc24

您只需执行一次,因为其他 UUID 仅相差几位数。

读取 = e093f3b6-00a3-a9e5-9eca-40026e0edc24

写入 = e093f3b7-00a3-a9e5-9eca-40036e0edc24

pYYBAGOYqPyAYkUBAAGUKO10oeI019.png
所有的块
 

如果你的蓝牙模块看起来不同,你必须看看这个:

 

基本上,在 4:24,您必须导入 BLE 扩展。为了节省您的搜索时间,您可以从此页面下载最新版本

以下是我们设想应用程序的工作方式:

我们首先扫描 BLE 设备,然后我们使用计时器在稍有延迟后连接到 MAC 地址(您可以使用 RSL10 Sense and Control App 找到您的 MAC)。连接后,我们停止扫描,禁用计时器并启用向上和向下按钮。接下来,我们注册字符串以侦听 RSL10-SENSE-DB-GEVK 数据。我们需要一个将值写回设备的过程。第一次使用此过程时,我们先发送 +1,然后发送 -1。这是启动接收高度字符串强制刷新手机号码所必需的。

同样在这些块中,我们有一个退出按钮,以及几个按钮来增加和减少高度 50 英尺。收到字符串后,我们将删除其中的括号并显示当前高度值。

我导出了 aia 文件,然后在本教程结束时将其上传到项目存储库中的 Github。我试图发布 appinventor 项目,但该网站不允许我发布。

poYBAGOYqP6AVvXwAAAaLhJwtCk539.png
 

硬件:

我非常喜欢 RSL10-SENSE-DB-GEVK 硬件,我考虑从本节开始而不是软件。板上有五个孔,其中四个可用于 I2C 连接。我有一个 OLED 正在等待一个项目,所以我将它直接焊接到 RSL10-SENSE-DB-GEVK。

poYBAGOYqQKAR-FpAAIYM-qJvCo074.png
连接板到 OLED
 
pYYBAGOYqQWAfv-0AAB3bMrn3QY512.png
调整 OLED 引脚以与电路板对齐并添加绝缘胶带
 
pYYBAGOYqQeAU73xAAEFss6btzo076.png
适合牙线盒
 
poYBAGOYqQmAEGdoAAE_yDwljpg995.jpg
比 Audible Abby 更紧凑
 
 

在尝试将 ALTER 移动到我可以像手表一样戴在手上的情况下,我设法打破了第一个 OLED 显示屏。此外,我损坏了第二个显示器,雪上加霜,我在此过程中破坏了 SCL 和 SDA 针孔。现在是个人的。

这里有几个选项可以推进项目:

  • 像一些“制造商”在 YouTube 上做的那样伪造它——如果你伪造它,你将永远无法做到
  • 买一块新板——它只有 50 块骨头,哟
  • 使用 Arduino Pro Mini 从 RSL10-SENSE-DB-GEVK 上可用的最后一个引脚 (GIO) 获取 UART 数据,然后通过 Arduino 的 I2C 将其发送到 OLED

我开始沿着最后一个选项的路径与我们尚未讨论的另一个选项并行。

使用 Arduino Pro Mini 选项的问题之一是我拥有的两个是 5V,与 RSL10-SENSE-DB-GEVK 或 OLED 电压不兼容。我不仅要扩大 CR2032 电源的尺寸以适应 OLED,还必须考虑另一块板的电源要求。

我们将带着悬念离开本节,但在继续下一节之前,我们将简要讨论一下外壳。

我必须能够在瓶盖内安装 Arduino Pro Mini 以及 RSL10-SENSE-DB-GEVK、OLED 和电池。最重要的是,它必须是蓝色的。

 
poYBAGOYqRaAAZJsAACjfiV3HqI363.jpg
 
1 / 6第 1 步:找一个蓝色瓶盖的瓶子
 

固件:

当我开始使用 Eclipse 时,我没有任何使用经验,但是我能够使用这个文档进行恢复出厂设置我很快意识到我必须找到一个例子来修改和在这个项目中使用。

pYYBAGOYqRiARgU1AABNl-By-zE780.png
这是我的出发点
 

我选择了“自定义服务固件”,因为它具有 BLE 和 BME680 代码。它也没有深度睡眠代码带来的并发症。如果代码太多,您可以随时删除或注释掉,就像我们即将在这里做的那样。如果这看起来工作量太大,请不要担心,我在本教程结束时将最终的工作合并代码上传到 Github 项目存储库。

如果您想了解更多信息,请继续阅读,或者直接跳到下一部分。

就像 Audible Abby 一样,ALTER 需要计算高度。我们将使用来自车载集成传感器的压力和温度数据来计算地面以上值的变化。ALTER 还需要在 OLED 屏幕上显示实时高度,但 ON Semiconductor IDE 中没有示例说明如何做到这一点。我尝试了几件事,但拯救的是一个不太可能的项目,这是我在 2019 年唯一没有赢得的比赛。

我从这里获取了 5 个文件,并对其进行了修改,以使它们与 RSL10-SENSE-DB-GEVK 一起使用,就像使用 Azure Sphere Starter-Kit 一样。我将这些文件放在工作区的 2 个文件夹中:

  • src\oled.c
  • src\sd1306.c
  • 包括\font.h
  • 包括\oled.h
  • 包括\sd1306.h

运行代码会导致一些错误,这很好,因为我可以注释掉导致问题的代码。这是我为清理这个烂摊子所做的事情:

  • sd1306.h像这样注释掉第 8 行和第 9 行//#include "i2c.h" //#include 并添加#include
  • oled.h像这样注释掉第 9、10、11 和 58 行//#include "applibs_versions.h" //#include //#include "deviceTwin.h" //uint8_t SSID[ WIFICONFIG_SSID_MAX_LENGTH];
  • oled.c像这样注释掉第 24、25、26、27、64、65、66、67 和 287行 //extern uint8_t oled_ms1[CLOUD_MSG_SIZE]; //extern uint8_t oled_ms2[CLOUD_MSG_SIZE]; //extern uint8_t oled_ms3[CLOUD_MSG_SIZE]; //extern uint8_t oled_ms4[CLOUD_MSG_SIZE]; //sd1306_draw_string(OLED_LINE_1_X, OLED_LINE_1_Y, oled_ms1, FONT_SIZE_LINE, white_pixel); //sd1306_draw_string(OLED_LINE_2_X, OLED_LINE_2_Y, oled_ms2, FONT_SIZE_LINE, white_pixel); //sd1306_draw_string(OLED_LINE_3_X, OLED_LINE_3_Y, oled_ms3, FONT_SIZE_LINE, white_pixel); //sd1306_draw_string(OLED_LINE_4_X, OLED_LINE_4_Y, oled_ms4, FONT_SIZE_LINE, white_pixel); //sd1306_draw_string(sizeof(str_SSID)*6, OLED_LINE_1_Y, network_data.SSID, FONT_SIZE_LINE, white_pixel);
  • sd1306.c我们这里有几行不能只注释掉;我们必须找到替代品。第 48 行变为:retval = HAL_I2C_Write(addr, data_to_send, 2, false); //I2CMaster_Write(i2cFd, addr, data_to_send, 2); 第 73 行变为:retval = HAL_I2C_Write(addr, data_to_send, 1025, false); //I2CMaster_Write(i2cFd, addr, data_to_send, 1025);
  • font.h我确实修改了该文件以使 0 和 1 看起来更好。您会认为微控制器可以使这两个正确!{0x3E, 0x51, 0x49, 0x45, 0x3E} 变为 {0x3E, 0x41, 0x41, 0x41, 0x3E} {0x04, 0x02, 0x7F, 0x00, 0x00} 变为 {0x00, 0x02, 0x7F, 0x00, 0x00}

您会在 oled.c 中找到的另一件事是从第 698 行开始的徽标。互联网上有很多关于如何创建自己的 OLED 徽标的教程。我使用了 LCDAssistant ,但您也可以使用http://javl.github.io/image2cpp/这是一个在线解决方案,可以将图像转换为 C 可以理解的数字。

在我们继续固件之前,让我们回到硬件部分。还记得我说过我没有 SCL 或 SDA 吗?这意味着 src\sd1306.c 中的第 48 行和第 73 行将无法向 OLED 发送任何内容。我刚刚添加了它们,因为你可能还有你的 I2C 引脚。

如果你想使用 UART,你必须在里面找到并修改 PinNames.h

C:\Users\<...>\PACK\ONSemiconductor\BDK\1.12.1\include\target\RSL10_SENSEPIN_UART_TX = NC 和 PIN_GIO_SPARE = PIN_DIO3替换为PIN_UART_TX = PIN_DIO3 和 PIN_GIO_SPARE = NC

由于我也没有使用 UART,正如您很快就会发现的那样,我对 PinNames.h 所做的唯一更改是 PIN_BUTTON0 = NC 和 PIN_GIO_SPARE = NC。

UART 对我来说是 B 计划,因为我正在努力制作与 I2C 功能相似的东西。就在那时我发现了 Bit Banging(是的,它听起来很酷)。那里有很多 Bit Bangers,但我发现Kevin Darrah的教程对于理解 I2C 协议的基础知识非常有用。我还必须使用GreatScott的教程来学习端口操作的概念。RSL10-SENSE-DB-GEVK 不是 Arduino,因此,我不得不相应地调整代码。想知道为什么我们需要端口操作吗?

 

您可能会说“UART 只需要一根线,但 I2C 需要两根线。您只剩下一个位置可以在板上焊接一根线。您将如何实现 Bit Banging I2C?” 我回复:

poYBAGOYqRuAUpXEAAEiN7MjXzM864.jpg
将另一根电线焊接到 DIY GPIO 的按钮上
 

ICYMI,我将一根电线焊接到一个按钮的未接地侧。

在 sd1306.c 第 49 行现在是:retval = SWI2C(data_to_send, 2); 现在第 74 行是:retval = SWI2C(data_to_send, 1025);

我们还需要两个文件:BitBanging.c 和 BitBanging.h。确保将 #include 添加到 main.c。您还应该添加 BitBanging_Init(); 在无限循环和 SendAltitudeToDisplay() 之前;在里面。

在 C:\Users\<...>\PACK\ONSemiconductor\BDK\1.12.1\source\firmware\BoardSupport\hb\src\ics 中找到 CS.c 并在顶部添加以下行:

#include <BitBanging.h>
#include 
int InitialAlt = -9999;
int OffsetAlt;
int AGL;
int PreviousAGL = -9999;

您还需要添加几个程序:

int CalculateAltitude(float P, float T) {
    // Get Altitude from Pressure and Temperature
    return (int) ((pow(P / 101.325, 0.190223) - 1) * (T * 280.4137 + 128897.8));
}
void SendAltitudeToDisplay(void) {
    // Save the response values
    float ResponseP, ResponseT;
    // Send a request in a specific format
    cs.node[1]->request_handler((struct CS_Request_Struct[] ) {{ "5", "EV", "P" }}, cs_node_response);
    // Save Pressure value
    ResponseP = atof(&cs_node_response[2]);
    if (ResponseP != 0.00) {
        // Send a request in a specific format
        cs.node[1]->request_handler((struct CS_Request_Struct[] ) {{ "6", "EV","T" }}, cs_node_response);
        // Save Temperature value
        ResponseT = atof(&cs_node_response[2]);
        // Right align text on OLED
        char TextBuffer[5];
        // Check if baseline altitude has been set
        if (InitialAlt == -9999) {
        // Set baseline
        InitialAlt = CalculateAltitude(ResponseP, ResponseT);
    } else {
        // Measure from baseline and take into account external Altitude adjustment
        AGL = InitialAlt - CalculateAltitude(ResponseP, ResponseT) + OffsetAlt;
        // Less than 1000 feet
        if (AGL < 1000) {
            // Print into 4 places to right align text on OLED
            snprintf(TextBuffer, sizeof(TextBuffer), "%4d", AGL);
        } else {
            // Less than 10000
            if (AGL < 10000) {
                // Print whole number into two places and one after the decimal
                snprintf(TextBuffer, sizeof(TextBuffer), "%2d.%d",AGL / 1000, AGL % 1000 / 100);
            } else {
                // Just use all of OLED
                snprintf(TextBuffer, sizeof(TextBuffer), "%d.%d",AGL / 1000, AGL % 1000 / 100);
            }
        }
        // Send to OLED if it has been more than 0.2 seconds since last update
        ////if (HAL_Time() - TimeStamp > 200) {
        //sd1306_draw_string(0, 15, TextBuffer, 5, white_pixel);
        // Loop through digits
        for (uint16_t k = 0; k < 4; k++) {
            // Remove ASCII offset
            char digit = TextBuffer[k] - 48;
            // Adjust if decimal point or negative
            if (digit < 0) digit = digit + 13;
            // Loop through pages
            for (uint16_t j = 0; j < 8; j++)
                // Columns of each page
                for (uint16_t i = j * 128; i < j * 128 + 32; i++)
                    // Copy to OLED buffer in specific order
                    if (digit >= 0)
                        oled_buffer[i + k * 32] = Image_num_bmp[i - (j * 128) + (j * 32) + (digit * 256)];
                    else
                        // If blank
                        oled_buffer[i + k * 32] = 0x00;
        }
        // Send OLED buffer to sd1306
        WriteBufferToDisplay();
        // Send via BLE only if AGL value has changed
        if (PreviousAGL != AGL) CS_PlatformWrite(TextBuffer, sizeof(TextBuffer));
        TimeStamp = HAL_Time();
        PreviousAGL = AGL;
        ////}
    }
}
}

此外,在 CS.c 中,您需要将以下内容添加到 CS_Loop(当然,在“int errcode, bytes, i;”之后)

// Read available BLE packet
memset(cs_rx_buffer, 0, 21);
CS_PlatformRead(cs_rx_buffer, 21, &bytes);
// New packet available
if (bytes > 0) {
// New AGL offset
OffsetAlt = OffsetAlt + atoi(cs_rx_buffer);
// Fore update BLE
PreviousAGL = -9999;
}
// We're done here
return 0;

我插入了 x = x+ 大小;在 sd1306.c 的第 770 行,只是为了在数字之间添加一些空格。最后,注释掉 main.c 中的以下几行以获得急需的速度:ASSERT_ALWAYS(CSN_ALS_CheckAvailability() == true); ASSERT_ALWAYS(CS_RegisterNode(CSN_ALS_Create()) == CS_OK); ASSERT_ALWAYS(CSN_AO_CheckAvailability() == true); ASSERT_ALWAYS(CS_RegisterNode(CSN_AO_Create()) == CS_OK); ASSERT_ALWAYS(CS_RegisterNode(CSN_PB_Create()) == CS_OK);

TL;博士:

pYYBAGOYqSCAdAN3AAB7eAptsSw699.jpg
 

 

 

结论:

在构建这个项目时,我花了数百个小时享受乐趣和学习。在没有任何特殊门户、额外的 MCU 甚至外部传感器的情况下,我能够如此快速地推出最小可行产品给我留下了深刻的印象。对我来说,这真的很强大。回顾之前的比赛,很多提交的作品都是使用硬件和软件,几乎没有修改,但这不是我的 MO 同时,我希望我的定制是可重现和可维护的,启用 RSL10-SENSE-DB-GEVK 的灵活性我来改变我的想法。

ALTER 只是一个开始,可以扩展到记录跳跃、总自由落体时间、垂直速度等。它也可以被修改以供飞行员使用,他们通过 BLE 应用程序更新气压以获得飞行中的准确高度在 OLED 显示屏上。天空才是极限!

我希望你发现这个项目很有用,并且和我一样喜欢它。我不希望看到很多使用 BLE、OLED 甚至 GPIO 的提交。因此,我希望安森美半导体可以使用这个项目或其中的一部分作为示例,让其他人从中受益并在此基础上再接再厉。

pYYBAGOYqS-AYwRSAAPpXC2r6Sg750.jpg
开启!
 

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"//www.hzfubeitong.com/m/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="https://m.elecfans.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'Arduino蓝牙低能耗跳伞高度计',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.hzfubeitong.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);