Actionscript3 для Arduino: отправка символа новой строки после массива целых чисел

Я хочу отправить массив целых чисел из приложения as3, которое я пишу во Flash Pro, на Arduino Uno, который будет использовать их для непрерывного позиционирования и изменения положения 5 сервоприводов. Таким образом, отправка 15 целых чисел позиционирует 5 сервоприводов, затем их переставляет, затем снова перемещает, затем возвращается в первую позицию и так далее. Затем я отправлял новый массив, заменяя старый, когда хотел.

Итак, мой tinkerproxy настроен между ними нормально (спасибо Майку Чемберсу и другим), и я написал обе стороны, чтобы они работали нормально при взаимодействии со своими последовательными мониторами. Но я не могу заставить их разговаривать друг с другом должным образом.

Моя проблема проста ... Я думаю ... Это как заставить as3 отправлять сигнал новой строки или какой-либо другой сигнал конца с массивом или после него, чтобы эскиз Arduino (с использованием serialEvent и parseInt для получения целых чисел, когда они отправляются), получив его, может пропустить parseInt и сделать что-то еще - в этом случае перейти к циклу и управлять этими надоедливыми сервоприводами.

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

АРДУИНО

/* 
   this sketch developed from arduino Tutorials ReadASCIIString + SerialEvent
   serialEvent can receive an array - 'buff' - of values from serial monitor
   loop can get those values and print some of them to prove it
   but I can't get Flash Pro (as3) to send the array: something to do with end of message character?
*/
#include <Servo.h>

int buff[100];//an array to hold integers from serial(arbitrary larger than ever needed size)
int j; //used to increment serial integer receipt in serialEvent
int patternLength;//=# of integers delivered over serial port, if followed by E or newline

void setup()
{
Serial.begin(9600);
Serial.setTimeout(2147483647);//25 days! so parseInt doesn't default to sending zeros every second
Serial.println("ready to go");//prints ok
}

void loop()
{
   for(int i=0; i<patternLength-4; i=i+5)//feed sets of 5 integers into 5 servos then repeats
    Serial.println(buff[i]);//prints 1st, 5th, 10th etc integer then repeats
    delay(1000);//so I can see it happening slowly enough
}//loops indefinitely until serialEvent interrupts to send new buff array values

void serialEvent()
{
     while(Serial.available()>0)
     {
     buff[j] = Serial.parseInt();
 Serial.println(buff[j]);//prints all integers sent if eg ','sent after last one
 j++;


 //if (Serial.read() == '\n')//works if serial monitor is set to 'newline' on sending
 if (Serial.read() == 'E')//works if no 'newline' + sending eg 1,2,3,4,5,6,7,8,9,10E

 //BUT how to send the equivalent of one of the above two 'endings' from Flash???
 //so that this part of the code executes
     {
     patternLength = j;  
     Serial.println("go to loop");
     j=0;//reset the index so next array sent replaces this one in 'buff' 
     }
 }

}

FLASH PRO ACTIONSCRIPT as3

/*
Simple Example that connects to an Arduino (via TinkerProxy) and sends
an array of integers for it to use. That doesn't work......

adapted from FlashBlink Created by Mike Chambers:

http://www.mikechambers.com/blog/2010/08/04/getting-started-with-flash-and-arduino/
*/


import flash.events.Event;
import flash.display.Sprite;
import flash.net.Socket;
//import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
//import flash.events.SecurityErrorEvent;
import flash.utils.Endian;
import flash.events.MouseEvent;

//my example of an array of integers I want to send to the arduino
var pattern:Array = [10,11,12,13,14,15,16,17,18,19,20];

//socket we will use to connect to TinkerProxy
var _socket:Socket;

//Address where TinkerProxy is located. Will usually be
//localhost / 127.0.0.1
var _proxyAddress:String = "127.0.0.1";

//port TinkerProxy is listening on
var _proxyPort:uint = 5331;

function onAddedToStage():void
{
    removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

    //create a Sprite to add to the stage.
    //This will be a simple button
    var s:Sprite = new Sprite();

    //draw a green square in the Sprite
    s.graphics.beginFill(0x00FF00);
    s.graphics.drawRect(0,0, 200,100);
    s.graphics.endFill();

    //Add Sprite to the display list
    addChild(s);

    //position it
    s.x = 50;
    s.y = 50;

    //listen for when the user clicks the Sprite
    s.addEventListener(MouseEvent.CLICK, onClick);

    _socket = new Socket();

    //Register for socket events

    //socket connected
    _socket.addEventListener( Event.CONNECT, onConnect );           

    //socket closed
    _socket.addEventListener( Event.CLOSE, onClose );           

    _socket.endian = Endian.LITTLE_ENDIAN;

    //connect
    _socket.connect(_proxyAddress, _proxyPort);
}

//called when we connect to the proxy server
function onConnect(event:Event):void
{
    trace("Socket Connected");
}

//called when the user clicks the button on stage
function onClick(event:MouseEvent):void
{
    trace("onClick");

    //make sure we are connected to the socket
    if(!_socket.connected)
    {
        //if not, don't do anything
        trace("You must be connected to send a command to the Arduino.");
        return;
    }

    var ENDOF:String = "E";

    for(var j:int = 0; j < pattern.length; j++)
        { 
        _socket.writeUTFBytes(pattern[j]); //send pattern array to Arduino
        trace(pattern[j]);//trace what I think I've just sent
        }
        //then send something as a last character - not an integer.
        _socket.writeUTFBytes(ENDOF);//send this string value to arduino
        trace("should have just sent an E, and sends an: " + ENDOF);
        //but how do I send this E conjoined to the last integer of the pattern array
        //so that Arduino responds by jumping out of serialEvent back to the loop?

        //flush the socket. Not really necessary, but here for forward compatibility.
        _socket.flush();
}

//called when the socket is closed
function onClose(event:Event):void
{
    trace("Socket Closed");
}

onAddedToStage();

person Paul Rua    schedule 31.10.2013    source источник


Ответы (1)


Ваш AS3 выглядит вполне достойно. Один небольшой момент: в onAddedToStage() вы удаляете прослушиватель событий со сцены, для которой вы никогда не регистрировались. Если вы действительно хотите, чтобы этот код запускался только после того, как шкала времени добавлена ​​в сцену, замените строку 114 следующим:

addEventListener(Event.ADDED_TO_STAGE, onAddedToStage)

Что касается вашего кода Arduino, я не разбираюсь в языке, который он использует (какой-то C?), Поэтому не стесняйтесь игнорировать следующее, если вам лучше.

  • Вы не инкапсулировали свой for цикл в строках с 22 по 24
  • Вы начали инкапсулировать свой while цикл в строке 30, но забыли закрыть его в строке 34
  • Вы объявили j, но не инициализировали его значение до строки 44 после того, как оно должно было использоваться в вашем while цикле в строке 33.

Наконец, чтобы ответить на ваш основной вопрос. Вы уже знаете, что новая строка записывается как \n, поэтому может показаться, что вам трудно читать это из Serial.read(). Прочитав документацию, я не смог найти ни одного типа данных, поэтому я предполагая, что вы имеете дело либо с ByteArray, либо со строкой. Предполагая, что это строка, моим первым побуждением было бы просто разделить ее на массив с помощью String.split (), но это не функция, доступная для String API. Другие (однако) написали это, и я считаю, что это упростит проблему, если предположить, что строки и Интцы могут успешно сосуществовать в этих типах объектов.

И наоборот, поскольку вы уже знаете, что размер этих чисел выражается в квинтетах, вместо того, чтобы использовать цикл while (строка 29), вы можете просто использовать for следующим образом:

#include <Servo.h>

int buff[100];
int j;
int patternLength;

void setup() {
    Serial.begin(9600);
    Serial.setTimeout(2147483647);
    Serial.println("ready to go");
}

void loop() {
    for(int i=0; i<patternLength-4; i=i+5) {
        Serial.println(buff[i]);
        delay(1000);
    }
}

void serialEvent() {
    if (Serial.available() > 0) {
        // This gaurantees we only pull the first 15 Ints into our buff array
        for (int k=0; k<15; k++)  {
            buff[j] = Serial.parseInt();
            Serial.println(buff[j]);
            j++;
        }

        patternLength = j;  
        Serial.println("go to loop");
        j=0;//reset the index so next array sent replaces this one in 'buff'
    }
}

Если приведенное выше не соответствует вам, вы можете отладить значение, которое вы фактически читаете из Stream, и протестировать его в своем операторе if в строке 37 с помощью:

Serial.println("Reading: " + Serial.read());

Надеюсь, это поможет.

-Ваше здоровье

person Atriace    schedule 31.10.2013
comment
Я вижу, что мне следует избегать комментариев типа «спасибо», но эй: спасибо. Наверное, мне понадобится несколько дней, чтобы пройти через это ... потом я вернусь с чем-нибудь настоящим! - person Paul Rua; 01.11.2013
comment
Arduino основан на обработке. Там нужны были скобки. Я думаю, что «while» не «for» допускает итерацию с parseInt, но для цикла «while» нужен символ «exit», иначе он останавливается на parseInt. Если он не видит, например, «100E», например, если это «100, E», parseInt просто зависает на «,» ждет 25 дней, а затем возвращает «0». Массивы могут быть от 5 до 50 или более целых чисел, поэтому нет свойства фиксированной длины, которое я мог бы использовать для перехода за пределы parseInt. Я сделал последний объект в массиве Flash строкой 100E, но это все равно не сработало. Arduino возвращает Чтение: + пробел! ?? - person Paul Rua; 06.11.2013
comment
Для ясности (1) Вы говорите, что не можете запустить parseInt, если он не входит в цикл while, и (2) вы не знаете, как закрыть цикл while, кроме символа выхода E, соединенного с длиной вашего buff массива? Я хотел бы обратить ваше внимание на arduino.cc/en/Reference/While, где вы буду замечать while (condition) только петли, в то время как (condition) истинно. Следовательно, вы можете выйти из цикла так же, как мы сделали for цикл: int k=0; while (k<15) { k++; } Если выход из цикла является вашей заботой, это правильный способ сделать это. - person Atriace; 06.11.2013
comment
Та. 1) правильно, потому что 2) я не могу придумать условие замыкания цикла. Я не знаю длины массива до его получения, поэтому я не могу использовать ваше предложение k ‹15. Итак, я выполнил arduino.cc/en/Tutorial/ReadASCIIString, используя массив, заканчивающийся новой строкой в цикл while, думая, что я могу отправить свои данные из Flash в этой форме, но пока не могу заставить это работать. Есть какие-нибудь идеи получше меня, чтобы проверить состояние? Время прошло, кажется ненадежным. Знаете, как отправить массив, заканчивающийся новой строкой во флэш-памяти, чтобы его можно было распознать как таковой код Arduino? - person Paul Rua; 07.11.2013
comment
Я полностью пропустил массивы, которые могут быть от 5 до 50 (моя проблема). По общему признанию, это было бы проще, если бы я мог протестировать вывод Serial.read (), независимо ... как указано в arduino.cc/en/Serial/Read, вашим условием может быть сам Serial.read () или другое экзотическое значение; даже ваш пробел подойдет. Поскольку метод выводит -1 при отсутствии данных, вы можете написать: while (Serial.read() != -1) { или прочитать один раз, сохранить в логическом значении и ссылаться на это логическое значение в условии: boolean go = true; while (go) { buff[j] = Serial.parseInt(); if (buff[j] == -1) {go=false}} - person Atriace; 07.11.2013
comment
Размещение Serial.read () там, где вы предлагаете, дает странно готовые к работе 11 Чтение: 12 Чтение: 13 Чтение: 14 Чтение: 15 Чтение: 16 7 8 9 0 Чтение: Чтение: - person Paul Rua; 08.11.2013