Терминал сбора данных на ардуино

lazy-fox
Offline
Зарегистрирован: 22.08.2014
В каждой торговой организации регулярно случается процедура инвентаризаций товара. Современное торгово-розничное предприятие содержит в базе до 15000 наименований номенклатуры и у каждого наименования может быть по несколько штриховых кодов на упаковке если такой товар производят на разных заводах. А бывает что на упаковке штрихкод отсутствует или не читается. Да и количество товара часто не единичное, но очень важно абсолютно точно счесть какое. Более того современная торговля тяготеет к круглосуточному режиму работы даже в праздничные дни. По-этому закрытие на переучёт это букет головной боли не только для предприятия, но и для покупателей.
 
Обычно для подсчёта остатков используются сканеры штрихкода в связке с ноутбуком где открыта учётная программа, или терминалы сбора данных которые накапливают в себе таблицу записей и при подключении к учётной программе формируют документ инвентаризации. Оба имеют недостатки: в первом мобильность весьма условна, во втором нет онлайн соединения при вводе. Моя идея в устройстве которое может работать по такому алгоритму: 
 
0. при включении устанавливаем беспроводное соединение с сервером (индикатор сеть и заряд акб)
1. вводим код товара с клавиатуры или сканером при нажатии клавиши СканШК получаем штрихкод
2. если код начинаестся с 29... - этикетка стеллажа - сохраняем в переменную номер витрины и переходим к пп1
3. выводим на дисплее код стеллажа (без кода стеллажа переходим к пп1)
4. выводим на дисплее код товара 
5. отправляем запрос наименования по коду товара на сервер
6. получение обратно наименования на терминал
7. выводим на дисплее наименование
8. вводим с клавиатуры количество товара
9. отправляем количество на сервер
10. принимаем и выводим подтверждение операции
 
 
lazy-fox
Offline
Зарегистрирован: 22.08.2014
Зная размер полей в базе определим экран: 6 строк по 20 символов: 60(в БД80)-наименование, 13-EAN13, 3-МХ, 14-операция, 6-статус. Размер полей и экран могут быть подобраны исходя из наглядности отображения информации.
Примерный интерфейс по алгоритму:
 
0 1234567890123456789
1 МХ:?    
3
4
 
0 1234567890123456789
1 В5:     Код:?      
3
4
 
0 1234567890123456789
1 В5:      4601546256541
2 Наименование: ?
3
4
 
0 1234567890123456789
1 В5:       4601546256541
2 фл Хлоргексидина би
3 глюконат 0,05 % 100м
4 л пласт фл-кап
5 кол-во: ?                 17      
 
0 1234567890123456789
1 В5:       4601546256541
2 фл Хлоргексидина би
3 глюконат 0,05 % 100м
4 л пласт фл-кап
5 17                          ОК
lazy-fox
Offline
Зарегистрирован: 22.08.2014
Поскольку задачей стоит инвентаризировать предприятие без остановки торговли, терминалами нужно обеспечить не только инвентаризаторов, но и кассиров.
 
Для инвентиризаторов схема работы:
Сканируем МХ, сканируем или вводим код товара, проверяем наименование, вводим кол-во, подтверждаем.  
Индикация сети и необходимости зарядки может быть светодиодной или в пятой строке первого и второго экрана.
Просмотр и редактирование ведомостей производится в интерфейсе инвентаризатора на ПК.
 
Для кассиров: 
При снятии товара с места хранения сканируем терминалом МХ и товар, подтверждаем, несём в зал продавать, 
если не продали откладываем в кассовую витрину. Это место инвентаризируется в последнюю очередь
 
Порядок инвентаризации: шкафы материальной, шкафы торгового зала, витрины, холодильники, прочие, некорректные, кассы.
Отсканированные терминалами инвентаризаторов записи добавляются к итогу.
Отсканированные терминалами кассиров записи вычитаются из итога.
Нераспроданный кассирами товар прибавляется к итогу (сканируется инвентаризационным терминалом)
lazy-fox
Offline
Зарегистрирован: 22.08.2014

Сетевые параметры ТСД получает по DHCP. По скольку терминал будет беспроводным в качестве канала передачи данных хорошо подойдёт WiFi. С одной стороны роутер решающий задачи маршрутизации и аренды адресов, с другой модули esp8266 для тсд.

Основой торговой системы в моём случае выбрана открытая СУБД Firebird. В других случаях может использоваться любая ODBC-совместимая система. При включении терминал читает параметры из таблицы config по id в БД учёта.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Ну и немного кода для общего представления системы.

Пока без алгоритма и с примитивными функциями, но что бы начать:

/*
Будем принимать по com-порту строку, выводим ее на экран и передавать ее на web-сервер
 Оборудование:
 - дисплей 1602, потенциометр для подсветки дисплея
 - Ethernet W5100 Shield Network Expansion Board w/ Micro SD Card Slot
 - web server
 
 Подключение дисплея 1602:
 Контакт дисплея  	Контакт Arduino	             Значение
 1	                       GND                   Vss
 2                            5V                    Vdd
 3                            GND	             Vo (контрастность)
 4	                       digital 9	     RS
 5	                       digital 8             R/W
 6	                       digital 7             ENABLE
 11	                       digital 6	     DB4
 12	                       digital 5	     DB5
 13	                       digital 3	     DB6
 14                           digital 2	     DB7
 15	                       5V	             LED+
 16                           GND	             LED-
 
 Подключение W5100:
 Обмен данными между Ардуиной и Шилдом происходит по SPI.
 Низким уровнем на digital выводе выбирает ведомое устройство на шине SPI:
 выбор SD - digital 4
 выбор ethernet - digital 10
 
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 */

// подключаем библиотеки
#include <LiquidCrystal.h>    // для работы с LCD
#include <SPI.h>              // для работы с SPI
// #include <SD.h>             // для работы с SD
#include <Ethernet.h>         // для работы с Ethernet

// инициализируем LCD, указывая контакты данных
LiquidCrystal lcd(9, 8, 7, 6, 5, 3, 2);

// задаем переменные
boolean receiveFlag = false;      // флаг что было что-то принято через com-порт
String myString;                  // строка
int Count = 1;                    // счетчик
int selectEthernet = 10;          // выбор ведомого на шилде - Ethernet
int selectSd = 4;                 // выбор ведомого на шилде - SD

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};   // mac адрес
byte ip[] = {
  192, 168, 1, 200};                      // ip если не получим из DHCP
byte gateway[] = {
  192, 168, 1, 101};                   // gateway
byte subnet[] = {
  255, 255, 255, 0};                  // маска сети
byte remote_ip[] = {
  192, 168, 1, 100};               // адрес сервера
char server[] = "vpn";    // name address server

// включим Ethernet
#define SWITCH_TO_W5100 digitalWrite(selectSd,HIGH); digitalWrite(selectEthernet,LOW);
// включим SD
#define SWITCH_TO_SD digitalWrite(selectEthernet,HIGH); digitalWrite(selectSd,LOW);
// выключим и SD и Ethernet
#define ALL_OFF digitalWrite(selectEthernet,HIGH); digitalWrite(selectSd,HIGH);

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP)
EthernetClient client;

void setup() {

  // красивая "загрузка" программы при старте :)
  lcd.begin(16, 2);
  lcd.print("Loading");
  delay(300);                // ждем 0.5 секунды
  lcd.print(".");
  delay(300);                // ждем 0.5 секунды
  lcd.print(".");
  delay(500);               // ждем 1 секунду

  Serial.begin(9600); // инициализируем передачу данных по COM-порту

  // Задаем режим работы портов  
  pinMode(selectEthernet, OUTPUT);
  pinMode(selectSd, OUTPUT);
  // высокий уровень на обоих - не выбран ведомый на SPI
  digitalWrite(selectEthernet, HIGH);
  digitalWrite(selectSd, HIGH);


  // старт Ethernet подключения
  if (Ethernet.begin(mac) == 0) 
  {
    lcd.print("Failed DHCP");
    // инициализируем без использования DHCP
    Ethernet.begin(mac, ip, gateway, subnet);
    // пауза 1 секунда - чтобы shield успел инициализироваться
    delay(1000);
  }
  // выведем локальный IP адрес
  lcd.clear();               //очистка экрана
  lcd.print("My IP address: ");
  lcd.setCursor(0, 1);      // устанавливаем курсор в 0-ом столбце, 2 строке
  for (byte thisByte = 0; thisByte < 4; thisByte++)  
  {
    // печатаем каждый байт IP адреса
    lcd.print(Ethernet.localIP()[thisByte], DEC);
    lcd.print("."); 
  }
  delay(1000);
  lcd.clear();               //очистка экрана
  lcd.print("Please scan...");
}

void loop() {

  // проверяем буфер com-порта - было ли что-то принято
  if (Serial.available() > 0)     //если есть доступные данные считываем строку
  {  
    while (Serial.available() > 0) 
    {
      int inChar = Serial.read();  // считываем символ
      myString += (char)inChar;    // формируем строку
    }  

    // устанавливаем флаг что нужно обработать принятые данные
    receiveFlag = true; 

    Serial.flush(); // очистим буфер
  }

  // если флаг receiveFlag установлен - значит что-то приняли. Обработаем 
  if (receiveFlag == true)
  {
    // выводим принятую переменную на экран
    lcd.clear();              //очистка экрана
    lcd.setCursor(13, 0);     // устанавливаем курсор в 12-ом столбце, 1 строке
    lcd.print(Count);         // выводим кол-во итераций
    lcd.setCursor(0, 1);      // устанавливаем курсор в 0-ом столбце, 2 строке
    lcd.print(myString);      // выводим myString на экран

    // отправим на сервер remote_ip GET запрос 
    // выберем ведомого SPI = включим ethernet        
    SWITCH_TO_W5100;

    // если удалось подключиться
    if (client.connect(remote_ip, 80)) 
    {
      String sid = "tsd1"; 
      String vitrina = "v01"; 
      String postsend = "POST /tsd/inv.php?s="+sid+"&v="+vitrina+"&q="+myString+" HTTP/1.1"; 
      //Serial.println("connected. "+postsend);
      client.println(postsend);
      client.println("Host: vpn");
      client.println("Connection: close");
      client.println();

      // рвем соединение
      client.stop();
    } 
    else 
    {
      // почему то не удалось подключиться к серверу
      lcd.print("connection failed");
    }   

    // отключим шилд от шины SPI (отключим все)
    ALL_OFF; 

    // подотрем за собой :)
    receiveFlag = false;      // сбрасываем флаг
    myString = "";            // очистка строки
    Count++;         // инкремент счетчика 
  }
  delay(1000);     // задержка перед повторением 
}

Запрос наим.товара из учётной БД:

SELECT PRODUCTS.PROD_NAME 
FROM BARCODES
   INNER JOIN PRODUCTS ON (BARCODES.BC_PRODUCT_ID = PRODUCTS.PROD_PRODUCT_ID)
WHERE (BARCODES.BC_BARCODE = $barcode)

К слову сказать web-сервер поднимать в каждой торговой точке я не собирался. Использовать публичный - рискованно (во время инвентаризации пропадёт интернет и что тогда?). Логично написать некого демона. Попробовал processing - не нашёл механизма работы с БД firebird. Написал udp клиент-сервер на Delphi (используя Interbase компоненту), но пока есть некоторые сложности с двусторонней диалоговой связью. Вероятно нарисую обработчик вроде http-odbc или http-FB. Режим связи в моем случае сильно похож на http клиента:

<запрос-{приём-передача-[выполнение-возврат]-передача}-приём>. []-sql, {}-демон, <>-терминал

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Источник вдохновения, используемый на данный момент:

Из беспроводных интерфесов ИК. Если бы можно было заменить на wifi и перешить ?)

Ну и что есть на текущий момент в железе:

Ethernet-shield собираюсь заменить на esp8266.

Однако он юзает rx/tx. Сканер ШК читает код по rx. Потребуется как то их переключать?

Читал про программное управление сом-портом, и про мегу-core. Что сможете посоветовать?

KVadik
KVadik аватар
Offline
Зарегистрирован: 15.06.2014

Тут можно собрать загрузчик с програмным UART, он (програмный UART) конечно сильно ограничен, но сканеру должно хватать.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Рабочая версия обработчика php-сервера:

<? 
//Глобальные переменные:
$database = "web:C:/Database/Database.gdb";
$table = "INV";
$user     = "SYSDBA";
$password = "masterkey";
$charset = "win1251";

//разбираем входные параметры
$TSD = $_REQUEST['tsd'];
$BARCODE = $_REQUEST['barcode'];
$QTY = $_REQUEST['qty'];
$PRODUCT = $_REQUEST['product'];
$MX = $_REQUEST['mx'];

// подключаемся к базе если это терминал
if ($TSD > 0) $db = ibase_connect($database, $user, $password, $charset) or die;

//спросим наименование если есть штрихкод товара
if ($BARCODE !='') {
	if ($QTY =='')  {
		$stn = "SELECT FIRST 1 PRODUCTS.PROD_NAME AS PRODUCT FROM BARCODES 
		INNER JOIN PRODUCTS ON (BARCODES.BC_PRODUCT_ID = PRODUCTS.PROD_PRODUCT_ID)
		WHERE (BARCODES.BC_BARCODE like $barcode)";
		$resultn = ibase_query($stn, $db) or die("Error_net_stn");
		while ($rown = ibase_fetch_assoc($resultn)) echo $rown['PRODUCT'];
	}
}

//запишем количество
if ($BARCODE !='') {
	if ($QTY !='') {
		$inst = "INSERT INTO $table (ID, TSD, DATETIME, BARCODE, PRODUCT, QTY, MX) 
		VALUES (GEN_ID (GEN_INV_ID,1), '$TSD', 'NOW', '$BARCODE', '$PRODUCT', '$QTY', '$MX')";
		$result = ibase_query($inst, $db) or die("Error_net_inst");
	}
}
@ibase_close($db); 
?>

Формат БД Firebird:

/******************************************************************************/
/***               Generated by IBExpert 14.11.2014 13:10:50                ***/
/******************************************************************************/
SET SQL DIALECT 3;
SET NAMES WIN1251;

/******************************************************************************/
/***                                 Tables                                 ***/
/******************************************************************************/
CREATE TABLE INV (
    ID        D_ID /* INTEGER NOT NULL;  GEN_ID (GEN_INV_ID,1) */,
    TSD       D_INT /* D_INT = INTEGER */,
    DATETIME  D_DATETIME /* D_DATETIME = TIMESTAMP */,
    BARCODE   D_BARCODE /* D_BARCODE = NUMERIC(14,0) */,
    PRODUCT   D_STR_80 /* D_STR_80 = VARCHAR(80) */,
    QTY       D_NUM_10_3 /* D_NUM_10_3 = NUMERIC(10,3) */,
    MX        D_BARCODE /* D_BARCODE = NUMERIC(14,0) */,
    INVID     D_INT /* D_INT = INTEGER */
);

/******************************************************************************/
/***                              Primary Keys                              ***/
/******************************************************************************/
ALTER TABLE INV ADD CONSTRAINT PK_INV PRIMARY KEY (ID);

/******************************************************************************/
/***                              Fields descriptions                       ***/
/******************************************************************************/
DESCRIBE FIELD ID TABLE INV
'Порядковый номер записи';

DESCRIBE FIELD TSD TABLE INV
'Номер терминала зашитый при производстве';

DESCRIBE FIELD DATETIME TABLE INV
'Время операции ввода данных';

DESCRIBE FIELD BARCODE TABLE INV
'Код по которому ищем товар';

DESCRIBE FIELD PRODUCT TABLE INV
'Наименование товара';

DESCRIBE FIELD QTY TABLE INV
'Подсчитанное количество';

DESCRIBE FIELD MX TABLE INV
'Код места хранения товара';

DESCRIBE FIELD INVID TABLE INV
'Порядковый номер инвентаризации (заполняется при выгрузке в учётную программу,
может быть использован для определения записей последней инвентаризации';

/******************************************************************************/
/***                               Generators                              ***/
/******************************************************************************/
CREATE GENERATOR GEN_INV_ID;
SET GENERATOR GEN_INV_ID TO 0;

Обращение к серверу:

пример запроса: web/tsd/inv.php?tsd=1&barcode=1251
ответ: уп Аллохол тб N24 

пример добавления записи: 
web/tsd/inv.php?tsd=1&barcode=1251&product=уп Аллохол тб N24&qty=2&mx=2978945612375

 

lazy-fox
Offline
Зарегистрирован: 22.08.2014
lazy-fox
Offline
Зарегистрирован: 22.08.2014

Ардуино код снова не даёт покоя.

Решил на терминале проверить штрихкод на принадлежность товару или услуге.

Из строки EAN-13 нужно прочитать первые два символа, и если они 29 то это этикетка шкафа, иначе товар.

 //проверим штрихкод: 29..-витрина, остальные-товар
    char vala = BARCODE.charAt(0);  //читаем 0 символ
    char valb = BARCODE.charAt(1);  //читаем 1 символ
    int len = BARCODE.length();         //длина стоки
    if (len = 14) {
      	if (vala='2') {
          if (valb='9') {
            MX = BARCODE;
  	    BARCODE ='';
          }
	}
    }

Результат: empty character constant! 

Решено: строка String "abc", первый символ строки Char 'a'. Дело в кавычках.

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Полный код с алгоритмом работы, но пока ещё с delay() и прочими подпорками:

/*
Будем принимать по com-порту строку, выводим ее на экран и передавать ее на web-сервер
 Оборудование:
 - дисплей 1602, потенциометр для подсветки дисплея
 - Ethernet W5100 Shield Network Expansion Board w/ Micro SD Card Slot
 - web server
 
 Подключение дисплея 1602:
 Контакт дисплея  	Контакт Arduino	             Значение
 1	                       GND                   Vss
 2                            5V                    Vdd
 3                            GND	             Vo (контрастность)
 4	                       digital 9	     RS
 5	                       digital 8             R/W
 6	                       digital 7             ENABLE
 11	                       digital 6	     DB4
 12	                       digital 5	     DB5
 13	                       digital 3	     DB6
 14                           digital 2	     DB7
 15	                       5V	             LED+
 16                           GND	             LED-
 
 Подключение W5100:
 Обмен данными между Ардуиной и Шилдом происходит по SPI.
 Низким уровнем на digital выводе выбирает ведомое устройство на шине SPI:
 выбор SD - digital 4
 выбор ethernet - digital 10
 
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 */

// подключаем библиотеки
#include <LiquidCrystal.h>    // для работы с LCD
#include <SPI.h>              // для работы с SPI
#include <Ethernet.h>         // для работы с Ethernet
// #include <SD.h>            // для работы с SD

// инициализируем LCD, указывая контакты данных
LiquidCrystal lcd(9, 8, 7, 6, 5, 3, 2);

// задаем переменные
boolean receiveFlag = false;      // флаг что было что-то принято через com-порт
boolean SendFlag = false;         // флаг что готовности отправки данных на сервер
char vala = '13';
char valb = '13';
String BARCODE = "";              // штрихкод
String TSD = "1";                 // ID-терминала (для каждого нового зашить свой)
String QTY = "";                  // количество товара
String PRODUCT = "";              // наименование товара
String MX = "";                   // место хранения
int selectEthernet = 10;          // выбор ведомого на шилде - Ethernet
int selectSd = 4;                 // выбор ведомого на шилде - SD

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};   // mac адрес
byte ip[] = {192, 168, 1, 200};                    // ip если не получим из DHCP
byte gateway[] = {192, 168, 1, 101};               // gateway
byte subnet[] = {255, 255, 255, 0};                // маска сети
byte remote_ip[] = {192, 168, 1, 100};               // адрес сервера
char server[] = "web";                               // name address server

#define SWITCH_TO_W5100 digitalWrite(selectSd,HIGH); digitalWrite(selectEthernet,LOW); // включим Ethernet
#define SWITCH_TO_SD digitalWrite(selectEthernet,HIGH); digitalWrite(selectSd,LOW); // включим SD
#define ALL_OFF digitalWrite(selectEthernet,HIGH); digitalWrite(selectSd,HIGH); // выключим и SD и Ethernet

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP)
EthernetClient client;

void setup() {

  // красивая "загрузка" программы при старте 
  lcd.begin(16, 2);
  lcd.print("Loading");
  delay(300);                // ждем 0.5 секунды
  lcd.print(".");
  delay(300);                // ждем 0.5 секунды
  lcd.print(".");
  delay(500);               // ждем 1 секунду

  Serial.begin(9600); // инициализируем передачу данных по COM-порту

  // Задаем режим работы портов  
  pinMode(selectEthernet, OUTPUT);
  pinMode(selectSd, OUTPUT);
  // высокий уровень на обоих - не выбран ведомый на SPI
  digitalWrite(selectEthernet, HIGH);
  digitalWrite(selectSd, HIGH);
  // старт Ethernet подключения
  if (Ethernet.begin(mac) == 0) {
    lcd.print("Failed DHCP");
    // инициализируем без использования DHCP
    Ethernet.begin(mac, ip, gateway, subnet);
    // пауза 1 секунда - чтобы shield успел инициализироваться
    delay(1000);
  }
  // выведем локальный IP адрес
  lcd.clear();                                          //очистка экрана
  lcd.print("My IP address: ");
  lcd.setCursor(0, 1);                                  // устанавливаем курсор в 0-ом столбце, 2 строке
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    lcd.print(Ethernet.localIP()[thisByte], DEC);       // печатаем каждый байт IP адреса
    lcd.print("."); 
  }
  delay(1000);
  lcd.clear();
  lcd.print("Please scan...");
}

void loop() {

  // проверяем буфер com-порта - было ли что-то принято
  if (Serial.available() > 0) {                            //если есть доступные данные считываем строку
    while (Serial.available() > 0) {
      int inChar = Serial.read();                          // считываем символ
      BARCODE += (char)inChar;                             // формируем строку
    }  
    receiveFlag = true;                                    // устанавливаем флаг что нужно обработать принятые данные
    Serial.flush();                                        // очистим буфер
  }
  if (receiveFlag == true) {                               // если флаг receiveFlag установлен - значит что-то приняли. Обработаем 
    //проверим штрихкод: 29..-витрина, остальные-товар
    char vala = BARCODE.charAt(0);
    char valb = BARCODE.charAt(1);
    int len = BARCODE.length();
    if (len = 14) {
      	if (vala='2') {
          if (valb='9') {
            MX = BARCODE;
  	    BARCODE ='';
          }
	}
    }
  receiveFlag = false;      // сбрасываем флаг
  }

// проверим что у нас есть из параметров до сеанса связи с сервером
// если не знаем места хранения, ждём сканирования витрины
 if (MX != "") {
// если знаем штрихкод товара, но не знаем наименования - делаем запрос наименования с сервера в PRODUCT   
   if (BARCODE != "") {
     if (PRODUCT == "") { 
        SWITCH_TO_W5100; // выберем ведомого SPI = включим ethernet     
        if (client.connect(remote_ip, 80)) {    // если удалось подключиться
          String postsend = "POST /tsd/inv.php?tsd="+TSD+"&barcode="+BARCODE+" HTTP/1.1"; // строка запроса:tsd=1&barcode=1251
          client.println(postsend);
          client.println("Host: web");
          client.println("Connection: close");
          client.println();
          if (client.available()) PRODUCT = client.read();           //принимаем в ответ наименование товара 
          client.stop(); // рвем соединение
         }
         else lcd.print("connection failed"); // почему то не удалось подключиться к серверу
         ALL_OFF; // отключим шилд от шины SPI (отключим все)
     }
   }
 } 

// если знаем штрихкод товара, знаем наименование, но не знаем количества - ждём ввода количества QTY
if (BARCODE != "") {
  if (PRODUCT != "") {
    if (QTY == "") {
     // выводим на экран
        lcd.clear();              //очистка экрана
        lcd.setCursor(13, 0);     // устанавливаем курсор в 12-ом столбце, 1 строке
        //lcd.print(Count);         // выводим кол-во итераций
        lcd.setCursor(0, 1);      // устанавливаем курсор в 0-ом столбце, 2 строке
        lcd.print(BARCODE);       // выводим на экран
      delay(1000);     // задержка перед повторением 
      // проверяем буфер клавиатуры - было ли что-то набрано
      // ждём ввод числа
    }
  }
}

// если знаем штрихкод товара, знаем наименование, знаем количество - ждём "ОК" или "Отмена"
if (BARCODE != "") {
  if (PRODUCT != "") {
    if (QTY != "") {
      // выводим на экран
        lcd.clear();              //очистка экрана
        lcd.setCursor(13, 0);     // устанавливаем курсор в 12-ом столбце, 1 строке
        //lcd.print(Count);         // выводим кол-во итераций
        lcd.setCursor(0, 1);      // устанавливаем курсор в 0-ом столбце, 2 строке
        lcd.print(BARCODE);       // выводим на экран
      delay(1000);     // задержка перед повторением 
      // ждём подтверждения ввода
      //if (OK = 1) SendFlag = true;
    }
  }
}

// если есть флаг - добавляем запись на сервере TSD+BARCODE+PRODUCT+QTY+MX
if (SendFlag == true) {
  SWITCH_TO_W5100; // выберем ведомого SPI = включим ethernet 
  if (client.connect(remote_ip, 80)) { // если удалось подключиться
    String postsend = "POST /tsd/inv.php?tsd="+TSD+"&barcode="+BARCODE+"&PRODUCT="+PRODUCT+"&QTY="+QTY+"&MX="+MX+" HTTP/1.1"; 
                      //    /tsd/inv.php?tsd=1&barcode=1251&product=уп Аллохол тб N24&qty=2&mx=2978945612375
    client.println(postsend);
    client.println("Host: vpn");
    client.println("Connection: close");
    client.println();
    client.stop();   // рвем соединение
    // подотрём за собой
    BARCODE = "";            
    PRODUCT = ""; 
    QTY = "";  
    SendFlag = false;
    } 
    else lcd.print("connection failed");    // почему то не удалось подключиться к серверу
    ALL_OFF;    // отключим шилд от шины SPI (отключим все)
  }

delay(1000);     // задержка перед повторением 
// в любой момент нажали на "Отмена" - очистили переменные BARCODE, PRODUCT, QTY
//    BARCODE = "";            
//    PRODUCT = ""; 
//    QTY = "";   
}

Что можно оптимизировать по существу?

Предстоит вывод кириллицы на экран Nokia5110 всместо 1602A, сетевой обмен esp8266 вместо w5100.

Работу сканера и чтение клавиатуры стоит обрабатывать по прерываниям? delay() заменить millis()

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Пришли посылки:

Экран : (Ну что же посмотрим на что он годится)

1. 4-board LED, backlight, light uniformity
2. PCB Size: 45 (mm) x 45 (mm)
3. the corners were positioning holes, along with two rows of the upper and lower connection port, ranked as follows:
    VCC - power input ( 3.3v )
    GND - Ground
    SCE - Chip Select
    RST - Reset
    D \ C - data / instruction selection
    DN - Serial Data Line
    CLK - Serial Clock Line
    LED - backlit console

WiFi: (Совсем микроскопический. как то даже в голове не укладывается.)

ESP8266

ESP8266 is a highly integrated chip designed for the needs of a new connected world. It offers a complete and self-contained Wi-Fi networking solution, allowing it to either host the application or to offload all Wi-Fi networking functions from another application processor.
ESP8266 has powerful on-board processing and storage capabilities that allow it to be integrated with the sensors and other application specific devices through its GPIOs with minimal development up-front and minimal loading during runtime. Its high degree of on-chip integration allows for minimal external circuitry, and the entire solution, including front-end module, is designed to occupy minimal PCB area.

Features
SDIO 2.0, SPI, UART
32-pin QFN package
Integrated RF switch, balun, 24dBm PA, DCXO, and PMU
Integrated RISC processor, on-chip memory and external memory interfaces
Integrated MAC/baseband processors
Quality of Service management
I2S interface for high fidelity audio applications
On-chip low-dropout linear regulators for all internal supplies
Proprietary spurious-free clock generation architecture
Integrated WEP, TKIP, AES, and WAPI engines
Solutions

Supports APSD for optimal VoIP applications
Patented spurious noise cancellation algorithm for integration in SOC applications
Supports Bluetooth co-existence interface
Self-calibrated RF to ensure optimal performance under all operating conditions
Zero factory tuning
No external RF components
Specifications

802.11 b/g/n
Wi-Fi Direct (P2P), soft-AP
Integrated TCP/IP protocol stack
Integrated TR switch, balun, LNA, power amplifier and matching network
Integrated PLLs, regulators, DCXO and power management units
+19.5dBm output power in 802.11b mode
Power down leakage current of <10uA
Integrated low power 32-bit CPU could be used as application processor
SDIO 1.1/2.0, SPI, UART
STBC, 1×1 MIMO, 2×1 MIMO
A-MPDU & A-MSDU aggregation & 0.4ms guard interval
Wake up and transmit packets in < 2ms
Standby power consumption of < 1.0mW (DTIM3)

Help your development more easy.
ESP8266 Serial WIFI Module Communite Forum;/a


1. High quality & low price
2. LWIP agreement
3. Support 3 modes: AP, STA, AP+STA
4. Perfect and simple AT commands

>>>>Translate data sheet Translate data sheet

>>>>Some translated document Some translated document</a>

>>>> Tutorial/a

 
Now your Arduino can get on WiFI without braking the bank.
Use this module for your next Interet of Things project, home automation, Or remote sensor project.
This module adats the ESP8226 IC for use over a serial connection using simple AT commands.
No SPI interface or Know-How is required. 
 
Warnings:
This module requires a 3.3 volt supply for VCC, and 3.3V logic. It is not 5V tolant. Connect RX or TX on 5V Arduino will
destroy this module. You must use a logic level converter, or a 3.3V Arduino

The 3.3V supply on the Arduino Uno has inadequate current capabilit to power this module. You must provide a separate,
higher 3.3V supply(about 300mA or better)

The ESP8225 module is very new on the market and support and documentation for it is currently very limited. 


Package Included:
1PCS* ESP8266 Remote Serial Port WIFI Transceiver Wireless Module AP+STA CZ

mini 2560 Mega2560-CORE (чувствую основной вес и габарит составляют разъёмы. Нужно будет их аккуратно выпаять вместе с кнопкой. Вопрос как минимизировать соединения?

Introduce

Mega2560-CORE is a small, complete and breadboard-friendly board base on the ATMega2560. Its design is based on the Arduino Mega2560,so we can use it as a Arduino Mega2560 development board. In a different place, it lacks only a 6-foot download port and a reset switch. Reducing the hardware circuit that can we reduce the power consumption and the cost. Mega2560-CORE has a matching download line and the other one end of the download cable is a USB interface, so it is very convenient for use.

Features
Ø  Microcontroller ATmega2560
Ø  Operating Voltage (logic level) 3.3V or 5 V
Ø  Digital I/O Pins 54 (of which 15 provide PWM output)
Ø  Analog Input Pins 16
Ø  DC Current per I/O Pin 40 mA
Ø  Flash Memory 256KB
Ø  SRAM 8 KB
Ø  EEPROM 4KB (ATmega2560)
Ø  Clock Speed 16 MHz
Ø  Low power consumption, low cost

 

JohnR
Offline
Зарегистрирован: 11.07.2017

Добрый день. Очень интересно чем дело закончилось? Уже наверное серийное производство наладили?:)

lazy-fox
Offline
Зарегистрирован: 22.08.2014

Дело закончилось иначе. Алгоритм работы сильно превзошел возможности железа. При расширении функционала надёжность сильно регрессировала. В результате база данных на firebird и php-обработчик сохранились, а терминал сваял на Android-смартфоне за рубль и получил достаточно мощный аппарат с надёжной связью и асинхронным интерфейсом взаимодействия, большим сенсорным экраном, русским интерфейсом. Изначально упор делался на аппаратный сканер штрихкода, который должен считать и передать запрос, а остальная часть была как бы вспомогательной, однако тесты показали важность как раз стадии контроля и принятия решения о записи, а так же корректировки. Сканирующий модуль был заменен фотокамерой, которую пришлось модернизировать для макросъёмки. Но в результате второй год в нашей торговой сети инвентаризации товара проходят без остановки торговли. Выборочные инвентаризации не новость, но при раздельном учёте по отделам (закрывается и считается отдел), а инвентаризации всех остатков сразу во время торговли я не встречал.

Производство не налаживал так как в первую очередь решалась частная задача. Конечно можно построить универсальное решение, но обсуждением темы мало кто заинтересовался. Разные торговые оргаинизации используют разные учётные системы. Одних версий, редакций и конфигураций 1С великое множество, не считая собственных и малоизвестных программ. Терминалы сбора данных продаются по той причине что они как чёрный ящик с формальным входом и выходом. Есть и программные терминалы как у меня и даже 1С нарисовала такой (но они все оффлайн, т.е. выгрузили таблицу кодов/наименований в ТСД - занесли отстатки- выгрузили ведомость обратно в БД). Я же решал задачу интегрированную в схему товародвижения. Изначально хотел расширить функционал ТСД при помощи ардуино, но в итоге вышел за рамки для завершения проекта. Если кому интересно - готов показать/настроить/сопроводить.