diff --git a/README.assets/144262e7fd3707720962e083d5304a7e.mp4 b/README.assets/144262e7fd3707720962e083d5304a7e.mp4
new file mode 100644
index 0000000..69a45aa
Binary files /dev/null and b/README.assets/144262e7fd3707720962e083d5304a7e.mp4 differ
diff --git a/README.assets/20230208200017.jpg b/README.assets/20230208200017.jpg
new file mode 100644
index 0000000..23cd009
Binary files /dev/null and b/README.assets/20230208200017.jpg differ
diff --git a/README.md b/README.md
index 5a5409f..7fd584f 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,23 @@ IO扩展板提供了
- doc为说明文档,包括开发和部署细节、硬件设计的描述等
- [deploy.md](./doc/deploy.md)为开发和部署说明,首先看这个文档
- [hardware_description.md](./doc/hardware_description.md)为PCB设计说明
-
- script为配置系统、安装环境、安装可执行文件、卸载可执行文件等的脚本
- protocol为上位机和下位机通信的协议
- hardware下位机主板、接口板、底板等的硬件设计
- source为可执行文件的源程序
+## 喷阀原理
+
+喷嘴由两片CNC加工的金属工件拼合而成,每一片工件上有48个深度为喷嘴宽度的一半的沟槽,两片拼合形成截面为矩形的48个喷嘴,通过软管连接到喷阀的气流出口。打开相应喷阀就会在喷嘴处射出气流。喷嘴以喷出气流向下的方向安装,整体平行于传送带滚筒,在传送带末端上方。如图:
+
+
+
+工作时射出的气流将瑕疵糖果向下吹走,正常糖果被传送带喷出,如下视频
+
+
+
+
+
## 版本
由于经常有不同类型的新要求出现,比如分选糖果、分选烟梗、同为糖果也具有不同的参数,因此不同的下位机型号(注意不是更新,比如同一台机器需要设置新的参数)应建立不同的分支,**主分支无实际意义**
diff --git a/doc/deploy.assets/20230208183606.jpg b/doc/deploy.assets/20230208183606.jpg
new file mode 100644
index 0000000..4436f18
Binary files /dev/null and b/doc/deploy.assets/20230208183606.jpg differ
diff --git a/doc/deploy.assets/5e6af30fa23d9.jpg b/doc/deploy.assets/5e6af30fa23d9.jpg
new file mode 100644
index 0000000..75f6f39
Binary files /dev/null and b/doc/deploy.assets/5e6af30fa23d9.jpg differ
diff --git a/doc/deploy.md b/doc/deploy.md
index e69de29..f2fe235 100644
--- a/doc/deploy.md
+++ b/doc/deploy.md
@@ -0,0 +1,67 @@
+# 下位机的部署步骤
+
+按下面标题的顺序进行,不要轻易跳过步骤,除非你知道你在做什么
+
+## 硬件连接
+
+### 启动方式选择
+
+EPC-9600I-L支持从NAND或者SD卡启动,通过 S7拨码开关控制,拨码开关如图全部设置为OFF,表示从NAND启动。
+
+
+
+### IO和供电连接
+
+完成以下步骤后,应如下图所示
+
+1. 将IO扩展板插入J1牛角座
+2. 按接线图连接相机触发线、编码器的任一相、阀板
+3. 按接线图连接IO扩展板的电源
+4. 按接线图连接EPC9600的电源
+5. 按接线图连接网线到交换机
+6. 连接调试用电脑到交换机
+
+
+
+
+
+启动交换机、EPC9600、IO扩展板的电源
+
+## 软件配置
+
+### 登录和配置
+
+断开并禁用电脑连接的其他网络和网络适配器(包括无线网),将电脑连接EPC9600的网口设置到192.168.1.0/24网络中
+
+SSH登录账号`root`,密码`root`
出厂默认IP为`192.168.1.136`
+
+可以使用任何SSH软件进行登录,推荐`Xshell`,连接后执行下面的命令设置新的时间和IP:
+
+```shell
+[root@epc-9600 ~]# date 2023.02.08-15:34:00
+[root@epc-9600 ~]# hwclock -w
+[root@epc-9600 ~]# eeprom net set ip 192.168.2.9
+```
+
+时间不要照抄上面的命令,设置为当前时间即可,IP必须为`192.168.2.9`,执行下面命令重启
+
+```shell
+[root@epc-9600 ~]# reboot
+```
+
+### 安装下位机软件
+
+因为设置了新的IP,所以将电脑连接EPC9600的网口设置为`192.168.2.11/24`,重新SSH连接IP为`192.168.2.9`的EPC9600。同时启动SFTP软件,推荐`Xftp`,将[script/S90target](../script/S90target)传输到EPC9600的`/tmp`中,运行下面命令配置下位机软件自启动:
+
+```shell
+[root@epc-9600 ~]# wr mv /tmp/S90target /etc/init.d/
+[root@epc-9600 ~]# wr chmod 755 /etc/init.d/S90target
+```
+
+用相同的放将本仓库release中`app.zip`解压出的下位机软件`target`传输到EPC9600的`/tmp`中,运行下面命令安装下位机软件:
+
+```shell
+[root@epc-9600 ~]# wr mv /tmp/target /root
+[root@epc-9600 ~]# wr chmod 755 /root/target
+[root@epc-9600 ~]# sync
+```
\ No newline at end of file
diff --git a/doc/version b/doc/version
index ceab6e1..2f45361 100644
--- a/doc/version
+++ b/doc/version
@@ -1 +1 @@
-0.1
\ No newline at end of file
+0.2
\ No newline at end of file
diff --git a/script/S90target b/script/S90target
new file mode 100644
index 0000000..f4976a9
--- /dev/null
+++ b/script/S90target
@@ -0,0 +1,2 @@
+#!/bin/sh
+/root/target &
\ No newline at end of file
diff --git a/script/version b/script/version
index ceab6e1..9f8e9b6 100644
--- a/script/version
+++ b/script/version
@@ -1 +1 @@
-0.1
\ No newline at end of file
+1.0
\ No newline at end of file
diff --git a/source/.vscode/c_cpp_properties.json b/source/.vscode/c_cpp_properties.json
index c775f0d..88eb59b 100644
--- a/source/.vscode/c_cpp_properties.json
+++ b/source/.vscode/c_cpp_properties.json
@@ -4,10 +4,10 @@
"name": "ARM",
"includePath": [
"${workspaceFolder}/**",
- "/home/miaow/software/arm-2011.03/lib/gcc/arm-none-linux-gnueabi/4.5.2/include/**"
+ "/home/miaow/software/gcc-arm-2011.03/lib/gcc/arm-none-linux-gnueabi/4.5.2/include/**"
],
"defines": [],
- "compilerPath": "/home/miaow/software/arm-2011.03/bin/arm-none-linux-gnueabi-gcc",
+ "compilerPath": "/home/miaow/software/gcc-arm-2011.03/bin/arm-none-linux-gnueabi-gcc",
"cStandard": "gnu99",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-arm",
@@ -15,7 +15,7 @@
"browse": {
"path": [
"${workspaceFolder}",
- "/home/miaow/software/arm-2011.03/lib/gcc/arm-none-linux-gnueabi/4.5.2/include"
+ "/home/miaow/software/gcc-arm-2011.03/lib/gcc/arm-none-linux-gnueabi/4.5.2/include"
]
}
}
diff --git a/source/.vscode/settings.json b/source/.vscode/settings.json
index f16e402..89a674d 100644
--- a/source/.vscode/settings.json
+++ b/source/.vscode/settings.json
@@ -16,7 +16,9 @@
"queue.h": "c",
"stdio.h": "c",
"encoder.h": "c",
- "semaphore.h": "c"
+ "semaphore.h": "c",
+ "socket.h": "c",
+ "host_computer.h": "c"
},
"makefile.launchConfigurations": [
{
diff --git a/source/Makefile b/source/Makefile
index 31b1c4e..9d4776c 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -1,5 +1,5 @@
#makefile for file_ioctl
-CROSS_COMPILE ?= /home/miaow/software/arm-2011.03/bin/arm-none-linux-gnueabi-
+CROSS_COMPILE ?= /home/miaow/software/gcc-arm-2011.03/bin/arm-none-linux-gnueabi-
TARGET := target
BUILD_DIR := build
diff --git a/source/gpio_common.h b/source/gpio_common.h
index 8fcc124..50bf405 100644
--- a/source/gpio_common.h
+++ b/source/gpio_common.h
@@ -1,3 +1,14 @@
+/**
+ * @file gpio_common.h
+ * @brief Operate the GPIO port of Zhou Ligong linux industrial control board
+ * @details is_file_exist(const char *file_path) determine whether the specified file exists
+ * print_array(int *array, int count) used to print out the value of the queue buffer, easy to debug and use
+ * @mainpage github.com/NanjingForestryUniversity
+ * @author miaow
+ * @email 3703781@qq.com
+ * @version v0.9.0
+ * @date 2021/12/25 merry christmas
+ */
#ifndef __GPIO_COMMON_H
#define __GPIO_COMMON_H
diff --git a/source/host_computer.c b/source/host_computer.c
index f910e09..5286261 100644
--- a/source/host_computer.c
+++ b/source/host_computer.c
@@ -1,9 +1,9 @@
/**
* @file host_computer.c
- * @brief Commnunicate with host computer. Protocal is described in hostcomputer通信协议.md
+ * @brief Commnunicate with host computer. Protocal is described in 下位机和上位机通信协议.md
* @author miaow (3703781@qq.com)
- * @version 1.0
- * @date 2022/01/16
+ * @version 1.1
+ * @date 2023/02/08
*
* @copyright Copyright (c) 2022 miaow
*
@@ -11,6 +11,7 @@
*
* | Date | Version | Author | Description
* |
|---|
| 2022/01/16 | 1.0 | miaow | Write this file
+ * |
| 2023/02/08 | 1.1 | miaow | Add fifo empty detection
* |
*/
#include
@@ -84,6 +85,16 @@ static int recvn(int fd, char *buf, int size)
return size;
}
+/**
+ * @brief Send string "error"
+ * @param fd The file descriptor that receives error
+ */
+static void send_error(int fd)
+{
+ write(fd, "error", 5);
+ printf("error sent\r\n");
+}
+
/**
* @brief To inspect the status of TCP connection
* @param sock_fd The socket
@@ -105,7 +116,7 @@ static int is_connected(int sock_fd)
void *loop_thread_func(void *param)
{
printf("loop thread in %s start\r\n", __FILE__);
- int need_exit = 0;
+ int need_exit = 0, error_sent = 0;
char pre;
uint16_t n_bytes;
char type[2];
@@ -143,39 +154,32 @@ void *loop_thread_func(void *param)
if (recvn(_global_structure.socket_fd, (char *)&pre, 1) > 1)
{
- // close(_global_structure.socket_fd);
printf("pre_len!=1\r\n");
continue;
}
if (pre != 0xAA)
{
- // close(_global_structure.socket_fd);
- // printf("%X ", (int)pre);
fflush(stdout);
continue;
}
if (recvn(_global_structure.socket_fd, (char *)&n_bytes, 2) != 2)
{
- // close(_global_structure.socket_fd);
printf("n_bytes_len!=2\r\n");
continue;
}
n_bytes = ntohs(n_bytes);
if (n_bytes > 4096 || n_bytes < 2)
{
- // close(_global_structure.socket_fd);
printf("n_bytes>4096 or n_bytes<2\r\n");
continue;
}
if (recvn(_global_structure.socket_fd, (char *)type, 2) != 2)
{
- // close(_global_structure.socket_fd);
printf("type!=2\r\n");
continue;
}
if (recvn(_global_structure.socket_fd, (char *)data, n_bytes - 2) != n_bytes - 2)
{
- // close(_global_structure.socket_fd);
printf("data_len!=n_bytes-2\r\n");
continue;
}
@@ -183,19 +187,16 @@ void *loop_thread_func(void *param)
data[n_bytes - 2] = 0;
if (recvn(_global_structure.socket_fd, (char *)check, 2) != 2)
{
- // close(_global_structure.socket_fd);
printf("check_len!=2\r\n");
continue;
}
if (recvn(_global_structure.socket_fd, (char *)&pre, 1) != 1)
{
- // close(_global_structure.socket_fd);
printf("end_len!=1\r\n");
continue;
}
if (pre != 0xBB)
{
- // close(_global_structure.socket_fd);
printf("end!=0xBB\r\n");
continue;
}
@@ -205,9 +206,9 @@ void *loop_thread_func(void *param)
if (type[0] == 'd' && type[1] == 'a')
{
// printf("%dbytes of data put to data queue\r\n", (int)n_bytes - 2);
- if (n_bytes - 2 != 6 * HOST_COMPUTER_PICTURE_ROW_NUM)
+ if (n_bytes - 2 != HOST_COMPUTER_PICTURE_BYTES)
{
- printf("n_bytes-2!=%d\r\n", 6 * HOST_COMPUTER_PICTURE_ROW_NUM);
+ printf("n_bytes-2!=%d\r\n", HOST_COMPUTER_PICTURE_BYTES);
continue;
}
int data_index = 0;
@@ -220,17 +221,24 @@ void *loop_thread_func(void *param)
for (int i = 0; i < HOST_COMPUTER_PICTURE_ROW_NUM; i++)
{
tmp_one_line_data = 0ul;
- for (int j = 0; j < 6; j++)
+ for (int j = 0; j < HOST_COMPUTER_PICTURE_COLUMN_BYTES; j++)
{
tmp_one_line_data <<= 8;
tmp_one_line_data |= data[data_index++];
}
queue_uint64_put(_global_structure.data_q, tmp_one_line_data);
}
+ // printf("queue_num=%d\r\n", _global_structure.data_q->nData);
+ if (_global_structure.data_q->nData == HOST_COMPUTER_PICTURE_ROW_NUM && !error_sent)
+ {
+ error_sent = 1;
+ send_error(_global_structure.socket_fd);
+ }
}
else if (type[0] == 's' && type[1] == 't')
{
// printf("Start put to cmd queue, param:%d\r\n", (int)atoll(data));
+ error_sent = 0;
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_START);
}
else if (type[0] == 's' && type[1] == 'p')
diff --git a/source/host_computer.h b/source/host_computer.h
index 19fbaf5..0e35783 100644
--- a/source/host_computer.h
+++ b/source/host_computer.h
@@ -1,9 +1,9 @@
/**
* @file host_computer.h
- * @brief Commnunicate with host computer. Protocal is described in hostcomputer通信协议.md
+ * @brief Commnunicate with host computer. Protocal is described in 下位机和上位机通信协议.md
* @author miaow (3703781@qq.com)
- * @version 1.0
- * @date 2022/01/16
+ * @version 1.1
+ * @date 2023/02/08
*
* @copyright Copyright (c) 2022 miaow
*
@@ -11,6 +11,7 @@
*
* | Date | Version | Author | Description
* |
|---|
| 2022/01/16 | 1.0 | miaow | Write this file
+ * |
| 2023/02/08 | 1.1 | miaow | Add 3 macros for picture from host computer
* |
*/
#ifndef __HOST_COMPUTER_H
@@ -23,6 +24,9 @@
#define HOST_COMPUTER_IP "192.168.2.10"
#define HOST_COMPUTER_PORT 13452
#define HOST_COMPUTER_PICTURE_ROW_NUM 500
+#define HOST_COMPUTER_PICTURE_COLUMN_NUM 48
+#define HOST_COMPUTER_PICTURE_COLUMN_BYTES (HOST_COMPUTER_PICTURE_COLUMN_NUM / 8)
+#define HOST_COMPUTER_PICTURE_BYTES (HOST_COMPUTER_PICTURE_COLUMN_BYTES * HOST_COMPUTER_PICTURE_ROW_NUM)
/**
* @brief The commonds, ref hostcomputer通信协议.md
diff --git a/source/main.c b/source/main.c
index e95c89c..5dbea1e 100644
--- a/source/main.c
+++ b/source/main.c
@@ -1,7 +1,25 @@
+/**
+ * @file main.c
+ * @brief Excuting commands, resample data, triggle camera, and send data to valve
+ * @author miaow (3703781@qq.com)
+ * @version 1.1
+ * @date 2023/02/08
+ *
+ * @copyright Copyright (c) 2022 miaow
+ *
+ * @par Changelog:
+ *
+ * | Date | Version | Author | Description
+ * |
|---|
| 2022/01/16 | 1.0 | miaow | Write this file
+ * |
| 2023/02/08 | 1.1 | miaow | Add debug option for interval of camera triggle
+ * |
+ */
#include
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -27,6 +45,11 @@ static int camera_trigger_pulse_count = 500;
static int valve_should_trigger_pulse_count = 1;
static int valve_trigger_pulse_count = 10;
static int camera_to_valve_pulse_count = 3015;
+#if defined(DEBUG_CAMERA_TRIG_PERIOD)
+static struct timeval tv;
+static uint64_t camera_period_interval_last_us = 0UL;
+static uint64_t camera_period_interval_us = 0UL;
+#endif
#define ROTATE_UINT64_RIGHT(x, n) ((x) >> (n)) | ((x) << ((64) - (n)))
#define ROTATE_UINT64_LEFT(x, n) ((x) << (n)) | ((x) >> ((64) - (n)))
@@ -69,19 +92,6 @@ int main(int argc, char *argv[])
hostcomputer_deinit();
queue_uint64_deinit(&data_queue);
queue_uint64_deinit(&cmd_queue);
-
- // encoder_init(on_encoder);
- // sleep(100);
- // encoder_deinit();
-
- // cameratrigger_init();
- // for (int i = 0; i < 100; i++)
- // {
- // sleep(1);
- // cameratrigger_trig();
- // }
- // cameratrigger_deinit();
-
return 0;
}
@@ -131,14 +141,21 @@ void process_cmd(uint64_t *cmd)
cameratrigger_deinit();
valve_deinit();
queue_uint64_clear(&data_queue);
+#if defined(DEBUG_CAMERA_TRIG_PERIOD)
+ printf("\r\n>>>>>\r\nstatus==SLEEPING\r\ncamera_period_us=%.2f\r\n<<<<<\r\n\r\n", (float)camera_period_interval_us / (float)(count_camera_continues - 1));
+ camera_period_interval_us = 0UL;
+ camera_period_interval_last_us = 0UL;
+#else
+ printf("\r\n>>>>>\r\nstatus==SLEEPING\r\n<<<<<\r\n\r\n");
+#endif
count_continues = 0UL;
count_valve_continues = 0UL;
count_camera_continues = 0UL;
- count_valve = 1;
count_camera = 0;
+ count_valve = 1;
count_valve_should_be = 2;
+
status = SLEEPING;
- printf("\r\n>>>>>\r\nstatus==SLEEPING\r\n<<<<<\r\n\r\n");
}
}
}
@@ -147,7 +164,7 @@ void valve_test(float ms_for_each_channel)
{
uint64_t valve_data = 1ul;
- for (int i = 0; i < 48; i++)
+ for (int i = 0; i < HOST_COMPUTER_PICTURE_COLUMN_NUM; i++)
{
usleep((useconds_t)(ms_for_each_channel * 500.0f));
valvedata.valvedata_1 = valve_data << i;
@@ -200,33 +217,34 @@ void on_encoder()
{
count_continues++;
+ // send resampled data to valve, the resample cycle is valve_trigger_pulse_count
if (++count_valve == valve_trigger_pulse_count + 1)
{
count_valve = 1;
count_valve_continues++;
valve_sendmsg(&valvedata);
-
- // printf("data:%llx send to valve, queue length is %d\r\n", valvedata.valvedata_1, data_queue.nData);
- // printf("%016llx ", valvedata.valvedata_1);
- // fflush(stdout);
}
+ // load valve data to valvedata structure
if (++count_valve_should_be == valve_should_trigger_pulse_count + 2)
{
count_valve_should_be = 2;
valvedata.valvedata_1 = 0;
queue_uint64_get(&data_queue, &(valvedata.valvedata_1));
- // if (data_queue.nData == 0)
- // {
- // printf("sb\r\n");
- // }
}
+ // triggle camera in a cycle of camera_trigger_pulse_count
if (++count_camera == camera_trigger_pulse_count)
{
- // printf("camera triggled\r\n");
count_camera = 0;
count_camera_continues++;
+#if defined(DEBUG_CAMERA_TRIG_PERIOD)
+ gettimeofday(&tv, NULL);
+ if (camera_period_interval_last_us != 0UL)
+ camera_period_interval_us += ((uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec) - camera_period_interval_last_us;
+ camera_period_interval_last_us = ((uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec);
+#endif
+
cameratrigger_trig();
}
}
diff --git a/source/main.h b/source/main.h
index 7ecc416..7fd4954 100644
--- a/source/main.h
+++ b/source/main.h
@@ -1,6 +1,23 @@
+/**
+ * @file main.h
+ * @brief Excuting commands, resample data, triggle camera, and send data to valve
+ * @author miaow (3703781@qq.com)
+ * @version 1.1
+ * @date 2023/02/08
+ *
+ * @copyright Copyright (c) 2022 miaow
+ *
+ * @par Changelog:
+ *
+ * | Date | Version | Author | Description
+ * |
|---|
| 2022/01/16 | 1.0 | miaow | Write this file
+ * |
| 2023/02/08 | 1.1 | miaow | Add debug option for interval of camera triggle
+ * |
+ */
#ifndef __MAIN_H
#define __MAIN_H
+// #define DEBUG_CAMERA_TRIG_PERIOD // uncomment this to print the interval of camera triggle in the unit of usecond
#endif
diff --git a/source/valve.h b/source/valve.h
index 4e1f710..48ff7f0 100644
--- a/source/valve.h
+++ b/source/valve.h
@@ -1,18 +1,28 @@
+/**
+ * @file valve.h
+ * @brief Operate the valveboard with Linux application
+ * @details Call valve_init() paired with valve_deinit() as their names imply, valve_send() can be executed several times to operate up to 6 valveboards between valve_init() and valve_deinit()
+ * @mainpage github.com/NanjingForestryUniversity
+ * @author miaow
+ * @email 3703781@qq.com
+ * @version v0.9.0
+ * @date 2021/12/25 merry christmas
+ */
#ifndef __VALVE_INIT_H
#define __VALVE_INIT_H
#include
typedef enum
{
- VALVE_SEN=GPIO_PINDEF_TO_INDEX(GPO1),
- VALVE_SCLK=GPIO_PINDEF_TO_INDEX(GPO2),
- VALVE_SDATA_1=GPIO_PINDEF_TO_INDEX(GPO0),
- VALVE_SDATA_2=GPIO_PINDEF_TO_INDEX(GPO3),
- VALVE_SDATA_3=GPIO_PINDEF_TO_INDEX(GPO4),
- VALVE_SDATA_4=GPIO_PINDEF_TO_INDEX(GPO5),
- VALVE_SDATA_5=GPIO_PINDEF_TO_INDEX(GPO6),
- VALVE_SDATA_6=GPIO_PINDEF_TO_INDEX(GPO7)
-}valve_pin_enum_t;
+ VALVE_SEN = GPIO_PINDEF_TO_INDEX(GPO1),
+ VALVE_SCLK = GPIO_PINDEF_TO_INDEX(GPO2),
+ VALVE_SDATA_1 = GPIO_PINDEF_TO_INDEX(GPO0),
+ VALVE_SDATA_2 = GPIO_PINDEF_TO_INDEX(GPO3),
+ VALVE_SDATA_3 = GPIO_PINDEF_TO_INDEX(GPO4),
+ VALVE_SDATA_4 = GPIO_PINDEF_TO_INDEX(GPO5),
+ VALVE_SDATA_5 = GPIO_PINDEF_TO_INDEX(GPO6),
+ VALVE_SDATA_6 = GPIO_PINDEF_TO_INDEX(GPO7)
+} valve_pin_enum_t;
typedef struct
{
@@ -24,12 +34,11 @@ typedef struct
uint64_t valvedata_6;
} valvedata_t;
-
#define SCLK_FREQUENCE_KHZ 10000
int valve_init(void);
-int valve_send(uint64_t* valve_data);
+int valve_send(uint64_t *valve_data);
int valve_deinit(void);
-int valve_sendmsg(valvedata_t* valve_data);
+int valve_sendmsg(valvedata_t *valve_data);
#endif
\ No newline at end of file
diff --git a/source/version b/source/version
index 9f8e9b6..b123147 100644
--- a/source/version
+++ b/source/version
@@ -1 +1 @@
-1.0
\ No newline at end of file
+1.1
\ No newline at end of file