Raspberry PI / PHP + Arduino последовательная связь - PullRequest
0 голосов
/ 21 сентября 2018

Я постараюсь дать краткое резюме проекта, а затем текущий подход к коду.

  • У меня установлен RPi с последней версией Stretch OS.
  • Я установил MySQL, PHP, APahce и PhpMyAdmin, и он работает правильно.
  • У меня он загружается до веб-страницы по умолчанию (локально размещенной) и в полноэкранном режиме (KIOSK).
  • БДсоздан, таблицы заполнены, запросы на месте ... и веб-страница (меню напитков) отображается правильно, как и ожидалось.

  • У меня Arduino UNO подключен к RPI через USB
  • На веб-странице отображается множество пунктов меню ... каждая со своей собственной кнопкой «Порядок».
  • При нажатии любой кнопки заказа. Я сохраняю данные этой кнопки в скрытом поле и используюjQuery для отправки / публикации формы (для себя)
  • После $ _POST я получаю эти отправленные данные и отправляю их через PHP через последовательную связь 1.

И вот гдеЯ в настоящее время.

  • Так как мой Arduino подключенЧерез USB к RPi.Я не могу использовать последовательный монитор для отладки вещей ... есть ли у меня какие-либо другие варианты здесь?

  • Когда я отправляю веб-страницу .. Я вижу RX / TXмигает индикатор на Arduino (заставляет меня поверить, что он получает последовательные данные) .. Я могу / буду проверять, правильно ли это сегодня вечером, снова подключив шаговый двигатель, и посмотреть, переместится ли t в правильное положение (я) ...

Вот где я немного застрял / зашел в тупик ... и мог бы использовать некоторые обсуждения, чтобы вывести меня на правильный путь.

Так что после Arduino 'делаетего магия "... он должен послать подтверждающее сообщение обратно в RPi .. сказать, что напиток готов ... и я могу вернуться в главное меню напитков в ожидании другого заказа

, поскольку веб-страница уже$ _POSTed..и последовательные данные, отправленные на подключенный Arduino .. .. Затем я покидаю страницу с сообщением "пожалуйста, подождите" ... но поскольку страница уже проанализирована на стороне сервера, у меня остаетсянеобходимость того, как «слушать»Серийный posrt теперь через PHP.

Я подумал ... Я мог бы использовать AJAX для вызова / загрузки внешнего php-скрипта ... который будет просто ждать / слушать последовательный порт ... и возвращать данные вAJAX обратный вызов «success».

Но так как я никогда не делал этого раньше ... Я немного подозреваю, сработает ли это ... или если это даже правильный способ сделать это.

Также случайные вопросы о лучших местах, чтобы открыть и закрыть порт .. особенно, если есть 2 отдельных сценария?(то есть: могу ли я открыть порт в одном скрипте ... и все же получить к нему доступ в другом? или этот файл обращается к нему ... должен быть тот, который открывает его?)

Вот мой текущий фрагментобрабатывать отправку и ожидание / прослушивание последовательного порта:

[код]

<?
if ($mode == 'submit') {

    //grab posted data (save to var)
    $drinkRecipe = $_POST['selectedDrink'];

    //set-up com port    
    exec("mode /dev/ttyACM0 BAUD=9600 PARITY=N data=8 stop=1 xon=off");
    //saw this on several RPi posts?  (but not sure of the difference? or why one would be used over the other?)
    //stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts

    //open serial port
    $fp = fopen("/dev/ttyACM0", "w+"); //w = write w+ = read/write

    //check if open
    if (!$fp) {
        echo "Not open";
        //die();
    } else {
        //if open send data (via PHP) to connected Arduino on serial comm port 1 (ttyACM0)
        fwrite($fp, '<' . $drinkRecipe . '>');


        //arduino takes serial data, parsed it.. does it duty, 
        //and is supposed to reply back via serial to the awaiting (listening) 
        //PHP script executed via AJAX, since the front end needs to display 
        //a 'waiting' type message.. and the callback 'success' will 
        //re-direct back to menu/initial state
        ?>
        <script type="text/JavaScript" language="JavaScript">
            $.ajax({
                //async: false,
                //type: "POST",
                url: "serial_listener.php",

                //define success handler actions
                success: function(response) {
                    //alert("PHP RETURN CHECK: "+response);
                    if($.trim(response) == 'complete'){
                        alert("Drink making is complete... return to main menu");
                        //do redirect here
                    }else{
                        alert("Some value other than 'complete' was returned... look into it!");
                        //not sure what to do? (back to main menu anyways?)
                    }
                },
                //define error handler actions
                error: function(response) {
                    alert("PHP SERIAL READ FAIL: "+ 'Ready State: '+ response.readyState + ' Status: ' + response.status);

                }
            }); 
        </script>       
        <?              

        //close connection
        fclose($fp); //needed? //should this go in the external php script instead now?

    }    

}

Даже не уверен, что должно войти в сценарий: serial_listener.php ... покапетля или что-то?В ожидании данных?или конец файла или что-то?(не уверен, как это работает с использованием fread () на последовательном порту?)

Любые предложения, чтобы попытаться обернуть мою голову, приветствуются.

Обновление: я не уверен, если яне объясняет правильно / четко?

Но когда страница отправляет (сама себе) .. это когда последовательные данные OUTGOING отправляются на подключенный (через USB к RPi) Arduino ....

Когда страница «отправляет», она отправляет вышеупомянутые данные OUT .., а затем отображает сообщение типа «пожалуйста, подождите».

На данный момент (насколько я понимаю) ..скрипт / синтаксический анализ на стороне сервера теперь завершен ... и у меня осталась страница с надписью "пожалуйста, подождите" ...

Больше нет парсинга на стороне сервера, НИЧЕГО не происходит в этот момент ..

Вот почему я подумал / поднял вопрос об использовании вызова AJAX для внешнего скрипта, который может сидеть и «ждать» (слушать) последовательный порт (неясно, как лучше всего это сделать ... какое-то время() цикл или что-то?) ...

и затем, когда данные в конечном итоге возвращаются ...

*

(что не говорит о том, сколько времени потребуется для этой «последовательной обратной связи» от Arduino… поскольку для создания каждого напитка требуется разное количество времени) .........

*

он будет использовать функцию обратного вызова AJAX 'success', чтобы затем обновить страницу .. и в конечном итоге просто перенаправить ее обратно в основной напитокстраница меню снова ... чтобы начать все сначала.

Я не чувствую, что использование timeout () или delay () на Arduino - это не только плохой совет (то есть: никогда не используйте delay (), если это может помочь)..... но я даже не вижу, где / почему это имеет какой-то смысл?


Обновление:

И содержимое скрипта serial_listener.php: (скрипт вызывает фрагмент кода AJAX)

//set-up com port    
exec("mode /dev/ttyACM0 BAUD=9600 PARITY=N data=8 stop=1 xon=off");

//open serial port
$fp = fopen("/dev/ttyACM0", "w+"); //w = write w+ = read/write

//check if open
if (!$fp) {
    echo "Not open";
    //die();

} else {

    while(!feof($fp)){
        $response = fread($fp, 10);
    }
    echo $response;
    fclose($fp);

}

Окончательное обновление:

Я переписал вещи, чтобы использовать вызов AJAX для отправки моих данных ... и также ждать ответа.Внешний php-скрипт, выполняемый вызовом AJAX, является ЕДИНСТВЕННЫМ местом, где сейчас открывается порт (а я его не закрываю)

Вот состояние SUBMIT формы PHP, в которой есть вызов AJAX:

Отправка данных работает 100% времени ... но я не могу прочитать мой ответ.

if ($mode == 'submit') {

    //grab posted data (save to var)
    $drinkRecipe = $_POST['selectedDrink'];

    ?>  
    <div id="waitingContainer">
        <p>Please wait, your brink is being made.</p>
    </div>

    <script type="text/JavaScript" language="JavaScript">
        console.log("ajax routine hit");

        //var drinkRecipe = "<?php echo $drinkRecipe ?>";
        var drinkRecipe = "<?=$drinkRecipe?>";

        var xhr = $.ajax({
            //async: false,
            type: "POST",
            url: "serial_listener.php",
            //datatype: "html",
            datatype: "text",
            data:({"drinkData":drinkRecipe}),
            //define success handler actions
            success:function(response) {
                //alert("PHP RETURN CHECK: "+response);
                if($.trim(response) == 'complete'){
                    console.log("Drink making is complete... return to main menu");
                    //do redirect here
                }else{
                    console.log("Some value other than 'complete' was returned... look into it!");
                    console.log("RESPONSE SENT WAS: " + response);
                    //not sure what to do? (back to main menu anyways?)
                }
                //kill the request
                xhr.abort();
            },
            //define error handler actions
            error: function(response) {
                console.log("PHP SERIAL READ FAIL: "+ 'Ready State: '+ response.readyState + ' Status: ' + response.status);
                //kill the request
                xhr.abort();
            }
        });     
    </script>
    <?             
}

Вот содержимое сценария serial_listener.php, который выполняет вызов AJAX:

//data sent from AJAX call (works)
$drinkData = $_POST['drinkData'];

//open serial port
$fp = fopen("/dev/ttyACM0", "w+"); //w = write w+ = read/write  (works)
//$fp = fopen("/dev/ttyUSB0", "w+"); //w = write w+ = read/write  //tried with USB-TTL cable too.. couldnt even send data)

//check if open
if (!$fp) {
    echo "Not open";
    //die();    
} else {

    if($drinkData != ''){   
        //send drink data
        fwrite($fp, '<' . $drinkData . '>');

        //wait for response
        $chars = "";
        do{
            $char = fread($fp, 1);
            $chars .= $char;
        }while(strlen($char) < 1);
        echo $char;
    }else{
        echo 'drink recipe is empty';
    }   
}

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Не могу комментировать, чтобы сделать предложение (без репутации) У меня нет знаний об Ajax, jquery, Raspberry Pi или PHP, но ...

Если у вас есть устройство TTL с последовательным интерфейсом USB, например this вы можете использовать библиотеку SoftwareSerial .Установите SoftwareSerial на пару неиспользуемых цифровых выводов на Arduino и отправьте туда отладочную информацию.

Не ответ, а предложение.

********* Редактировать***********

Если подумать, разве у Raspberry Pi нет последовательного порта?Если это так, вам не нужен конвертер USB.Просто установите программный порт на Arduino и используйте его для подключения к Pi.Таким образом, вы можете использовать порт USB для отправки отладочных комиксов на ваш компьютер.

0 голосов
/ 21 сентября 2018

Во-первых, у меня нет опыта ни с Raspberry, ни с Arduino, но я играл с последовательной связью в прошлом.Вы делаете вещи слишком сложными.Последовательное общение - это не странное животное из исторического канала - воспринимайте это как слой данных.Вы бы легко создали необходимые передний и внутренний интерфейс, если бы данные поступали из базы данных или шли в нее?Теперь внедрите вашу систему точно таким же образом, просто вместо соединения с базой данных используйте последовательную связь.

Ваш serial_listener прост:

  • создание / настройка порта
  • отправка данных
  • чтение данных
  • закрытие порта

Итак, весь случай:

внешний интерфейс --post (d) -> serial_listener :: COM1:: send (d) ... COM1 :: read ('OK') -> ответить 'success'

PS.с этими маленькими контроллерами ... timeout () ваш настоящий друг;)

А для последовательной связи я бы предложил использовать некоторую библиотеку (например, php_serial.class)


Я пытаюсьуточнить с кодом.Я стараюсь сделать это как можно проще, просто для иллюстрации системы в целом.

Внешний интерфейс, чистый js / html и AJAX-запрос:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body onLoad="$('#loading-image').hide();">


<div width="100%" style="text-align: center;">
    <div id="demo">
        <h2>Content: forms/scripts/...</h2>
    </div>
    <div>
        <button type="button"
            onclick="makeSerialCall('serial.php')">order (send AJAX call to php script)
        </button>
    </div>
</div>
<img id='loading-image' src='https://media.tenor.com/images/011ebf9c192d1c9b26f242d526ee24bb/tenor.gif'></img>


<script>
var string = 'data which is collected from content above';

function makeSerialCall(url) {
        $('#loading-image').show();
        $.ajax({
            type: "POST",
            url: url,
            data: string,
            cache: false,
            success: function(response){
                $('#loading-image').hide();
                console.log(JSON.stringify(response['info']));
                //and whatever else you want to do afterwards...
            }
        });
}
</script>
</body>

Серверная часть:

<?php
if(!empty($_POST))
  $data = $_POST["data"];

include "php_serial.class.php";

$serial = new phpSerial();
$serial->deviceSet("/dev/ttyUSB0");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");

$serial->deviceOpen();
$serial->sendMessage($data);
$read = $serial->readPort();
$serial->deviceClose();

header('Content-type: application/json');
$response_array['status'] = 'success'; 
$response_array['info'] = 'some additional info:'.$read;   
echo json_encode($response_array);
?>

Таким образом, у вас есть «загрузка ..» изображение на экране до ответа.Начальная страница отображается постоянно.Конечно, вам нужно много (ошибок) проверки, решения, когда нет ответа от последовательного и т. Д. И т. Д.Но базовая система - это не "ракетостроение".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...