FLProg-用C语言创建自定义块(不结余的课程)



最近,FLProg项目获得了很大的欢迎,我再也没有足够的时间为用户所需的外围设备创建模块。同时,在该网站的用户中,有足够多的人精通C语言,可以帮助我开发该程序。我决定给他们适当的工具。因此,在1.10.3版中,可以使用集成的C代码创建自定义块,这导致了相当意外的结果。该工具不仅对精通编程的用户感兴趣,而且对以前没有编写过代码的用户也很感兴趣。他们首先从编写简单的块开始(例如,获得对数-我在标准块中没有这样的块)以使用库的严重块结尾。因此,我想打破有关使用该程序的一些预想的课程顺序,而我将依次告诉您如何创建此类块。

在本课程中,将为数字指南针HMC5883L创建一个块。为单位的基础上已经采取了这一文章。图书馆是从这里拿来的
因此,运行程序并创建一个新项目。在元素库中,转到“自定义”选项卡,然后选择新块将位于的自定义块库的树枝。然后点击“创建块”按钮,



将打开一个窗口,其中包含该块的编程语言。提供FBD,LAD和代码语言。 LAD和FBD语言将在其他课程中讨论,现在选择“代码”。



用户块编辑器窗口打开。上部是参数选项卡(1),下部是代码段(2)。



我们填写主要参数。



块的输入和输出以相同的方式创建。我们的块将没有任何输入,因此我们跳过此选项卡,然后转到“块输出”选项卡。该块将具有三个输出-沿X,Y和Z轴的方向。要创建输出,请单击“添加输出”按钮。



登录创建窗口将打开。它与在主程序中创建变量的窗口非常相似,因此我将不对其进行详细描述。块的输出值以Float格式提交-因此,我们选择相同的输入类型。由于输出名称将出现在代码中,因此输出名称受到C语言中变量名称的限制。写评论没有任何限制。



以同样的方式,我们创建其余的输出。



现在,我们将设置用户在使用块时要设置的参数。这就是传感器的灵敏度。根据说明,从以下系列中进行选择:0.88、1.3、1.9、2.5、4.0、4.7、5.6、8.1

转到选项卡“用户设置”,然后单击“添加参数”按钮。



将打开一个用于创建用户参数的窗口。由于我们具有Float类型的参数,因此选择此类型。参数名称没有限制,因为在生成的代码中此名称将被参数值替换。评论文字也没有限制。



创建参数时,可以设置默认值。在这种情况下,使用块时,无需设置参数值。也可以设置参数值的边界,如果输入的值超出这些边界,则该块将被视为不正确。

现在让我们来照顾图书馆。让我们转到“库”标签。块工作中使用的库可以直接加载到块中。为此,请单击“下载库”按钮。



将打开一个用于选择带有库的文件夹的窗口。



选择库文件夹后,它将被加载到块中,并显示在已加载库的列表中。如有必要,可以加载几个库来运行该块。



在项目中使用块时,在编译方案之前,程序将检查库目录中该块中是否存在加载的库,如果没有,则将卸载丢失的库。

在“描述”选项卡上,最好写出如何使用本机,其用途等。此说明将帮助其他用户使用它。

现在转到代码区域

,第一个选项卡是“ DeclareSection”部分。在此选项卡上,您需要注册必需库的连接,变量,数组和结构的声明。我们将以库中的示例为指导填充本节。

示例中的“声明”部分的代码。
/*
HMC5883L_Example.pde - Example sketch for integration with an HMC5883L triple axis magnetomerwe.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk)

This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

// Reference the I2C Library
#include <Wire.h>
// Reference the HMC5883L Compass Library
#include <HMC5883L.h>

// Store our compass as a variable.
HMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;

// Out setup routine, here we will configure the microcontroller and compass.




转移到该块时,除去了不必要的注释,尽管除了C语言本身的用法之外,对其使用没有任何限制。还添加了一些变量,这些变量将在以后的代码中派上用场。在原始示例中,它们在“循环”部分中声明。在这里,它们被移至“声明”部分。



今天,在“声明”部分中,您可以使用任何类型的变量声明,数组和结构的声明。#define指令已正确处理
您不能使用这种类型的声明:

typedef struct{
...
...}
test;


必须以这种形式重做:

struct test{
...

...
};


您不能使用extern类型原来这是一个相当大的问题,我希望在不久的将来解决。

现在,让我们继续“ SetupSection”部分。在这里,代码从示例中几乎一对一传输。

示例代码
void setup()
{
  // Initialize the serial port.
  Serial.begin(9600);

  Serial.println("Starting the I2C interface.");
  Wire.begin(); // Start the I2C interface.

  Serial.println("Constructing new HMC5883L");
  compass = HMC5883L(); // Construct a new HMC5883 compass.
    
  Serial.println("Setting scale to +/- 1.3 Ga");
  error = compass.SetScale(1.3); // Set the scale of the compass.
  if(error != 0) // If there is an error, print it out.
    Serial.println(compass.GetErrorText(error));
  
  Serial.println("Setting measurement mode to continous.");
  error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
  if(error != 0) // If there is an error, print it out.
    Serial.println(compass.GetErrorText(error));
}




已从示例中删除了限制该节的节标题和括号(它们是程序在编译过程中插入的)。也将所有诊断输出移至该命令。这是发生了什么事。



请注意,代替了Precision参数,而是插入了Precision参数。编译块时,将插入用户输入的值而不是该名称。

现在让我们进入“循环”部分。

示例库中的原始代码
void loop()
{
  // Retrive the raw values from the compass (not scaled).
  MagnetometerRaw raw = compass.ReadRawAxis();
  // Retrived the scaled values from the compass (scaled to the configured scale).
  MagnetometerScaled scaled = compass.ReadScaledAxis();
  
  // Values are accessed like so:
  int MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis)

  // Calculate heading when the magnetometer is level, then correct for signs of axis.
  float heading = atan2(scaled.YAxis, scaled.XAxis);
  
  // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
  // Find yours here: http://www.magnetic-declination.com/
  // Mine is: 2” 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
  // If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
  float declinationAngle = 0.0457;
  heading += declinationAngle;
  
  // Correct for when signs are reversed.
  if(heading < 0)
    heading += 2*PI;
    
  // Check for wrap due to addition of declination.
  if(heading > 2*PI)
    heading -= 2*PI;
   
  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180/M_PI; 

  // Output the data via the serial port.
  Output(raw, scaled, heading, headingDegrees);

  // Normally we would delay the application by 66ms to allow the loop
  // to run at 15Hz (default bandwidth for the HMC5883L).
  // However since we have a long serial out (104ms at 9600) we will let
  // it run at its natural speed.
  // delay(66);
}




与“设置”部分中一样,删除部分标题和边界括号。它们将被程序自动插入代码中。我们还将在“循环”部分中删除变量的声明。在本节中,声明临时变量是非常不希望的,因为如果在项目中多次使用该块,则在重新声明变量时会发生错误。
结果就是这样的代码:



代码的结尾,我们调用Output函数(raw,scaled,heading,headingDegrees)。原则上,您可以不使用它,但我决定将其作为创建函数的示例。因此,转到选项卡“ FunctionSection”。
要创建新功能,请单击“添加功能”按钮。



输入函数标题的窗口将打开,我们在其中输入其定义。



创建标题后,编写功能代码。

示例中的原始功能代码
void Output(MagnetometerRaw raw, MagnetometerScaled scaled, float heading, float headingDegrees)
{
   Serial.print("Raw:\t");
   Serial.print(raw.XAxis);
   Serial.print("   ");   
   Serial.print(raw.YAxis);
   Serial.print("   ");   
   Serial.print(raw.ZAxis);
   Serial.print("   \tScaled:\t");
   
   Serial.print(scaled.XAxis);
   Serial.print("   ");   
   Serial.print(scaled.YAxis);
   Serial.print("   ");   
   Serial.print(scaled.ZAxis);

   Serial.print("   \tHeading:\t");
   Serial.print(heading);
   Serial.print(" Radians   \t");
   Serial.print(headingDegrees);
   Serial.println(" Degrees   \t");
}




我们在命令行中删除与输出相关的所有内容,并将值分配给块的输出。好吧,像往常一样,删除标题和边界括号。这是结果。



块上的工作已完成。

在块编辑器中工作时有点摆设。在代码的任何字段中,都可以使用上下文菜单插入输入,参数输出或函数调用模板的名称。



我们通过点击“退出”按钮完成工作。



保存该块后,它可以在项目中用作常规块。

对于大多数读完本书的患者来说,这是本课程的视频版本。

Source: https://habr.com/ru/post/zh-CN390267/


All Articles