Skip to content

Commit 6ebb7ea

Browse files
committed
Merge branch 'release/2.1.0'
2 parents 8936d21 + 897bd58 commit 6ebb7ea

File tree

7 files changed

+53
-40
lines changed

7 files changed

+53
-40
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
# Pano Controller
1+
# Pano Controller 2.1
22

33
Open Arduino-based Platform for high-resolution panoramic photography controlled via Bluetooth App.
44
Started as a board replacement/upgrade for the Gigapan EPIC 100, but designed to be
55
flexible and support home-brew panoramic platforms.
66

7-
The design goals for the new version 2.1 are as follows:
7+
The design goals for the new versions 2.1 and beyond are as follows:
88
1. (iOS) App is required to configure the device and start panorama (the platform cannot set up a pano without it)
99
2. (Arduino) Platform can complete a full pano once started, even if App disconnects
1010
3. (iOS) App may enhance operation during pano execution (by reading status and influencing parameters)
1111

1212
See the <a href="https://www.facebook.com/panocontroller">Official Facebook page</a> for demo videos and more progress photos.
1313

14-
Will need the <a href="https://github.com/laurb9/PanoController">Pano Controller iOS App</a> (also in development).
14+
Will need the <a href="https://github.com/laurb9/PanoController">Pano Controller iOS App</a>.
1515

1616
<img src="images/prototype.jpg" width="400" alt="Pano Controller 2.0 Executor Boards installed in Gigapan EPIC 100">
1717
<img src="images/pano-info.jpg" width="200" alt="Pano Controller 2.0 Information Display">
@@ -20,7 +20,7 @@ Will need the <a href="https://github.com/laurb9/PanoController">Pano Controller
2020
### Software
2121
- **<a href="https://www.facebook.com/panocontroller/videos/1009260305834819/">Zero-motion shutter delay!</a>**
2222
When gyro is connected, waits for platform to stabilize before triggering. Useful to compensate for tripod stability, platform's own movement or wind gusts.
23-
- **<a href="https://www.facebook.com/panocontroller/videos/1143955072365341/">Remote Control Demo (2.0)</a>**
23+
- **<a href="https://www.facebook.com/panocontroller/videos/1488324751261703/">Smooth movement and iOS App Demo (2.1)</a>**
2424
- Focal length presets from 12 to 600mm. Precise sub-degree movement control.
2525
- Seamless 360 pano option
2626
- Display:

examples/PanoController/PanoController.ino

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ void loop() {
288288
/*
289289
* BLE App async receive & execute thread
290290
*/
291-
app.poll(min(micros() - next_event_time, 20));
291+
app.poll();
292292
/*
293293
* Collect and send state to menu navigator
294294
*/
@@ -307,10 +307,12 @@ void loop() {
307307
if (!settings.motors_enable || state.running){
308308
app.sendStatus();
309309
displayPanoStatus(true);
310+
app.poll(20);
310311
}
311312
} else {
312313
display.clearDisplay();
313314
display.display();
315+
app.poll(20);
314316
}
315317
/*
316318
* In-progress pano execution

examples/PanoController/config.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
#define MOTOR_RPM 500
3232
// do these belong in platform settings ?
3333
// acceleration/deceleration in steps/sec^2
34-
#define MOTOR_ACCEL 300
35-
#define MOTOR_DECEL 100
34+
#define MOTOR_ACCEL 1000
35+
#define MOTOR_DECEL 500
3636

3737
// board-specific pin settings
3838
#if defined(ARDUINO_ARCH_SAMD) && defined(ARDUINO_SAMD_FEATHER_M0)

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=PanoController
2-
version=2.1.0-beta
2+
version=2.1.0
33
author=Laurentiu Badea
44
maintainer=Laurentiu Badea
55
sentence=Controller for high-resolution panoramic photography.

src/app_interface.cpp

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "app_interface.h"
1111

12+
#define UART_BUFFER_SIZE BLE_BUFSIZE
13+
1214
extern AppInterface app;
1315

1416
AppInterface::AppInterface(Adafruit_BluefruitLE_SPI& ble, PanoSettings& settings, PanoState& state)
@@ -32,13 +34,13 @@ void callbackGattRX(int32_t char_id, uint8_t* data, uint16_t len){
3234
}
3335
void callbackUartRX(char data[], uint16_t len){
3436
//{ debug
35-
Serial.print("BLE UART RX len=");
36-
Serial.print(len);
37-
Serial.print(" data=");
38-
for (int i = 0; i < len; i++) { Serial.print(data[i], HEX); Serial.print("-"); };
39-
Serial.println("");
40-
//} debug
41-
app.uartRX((uint8_t *)data, len);
37+
Serial.print("BLE UART RX len=");
38+
Serial.print(len);
39+
Serial.print(" data=");
40+
for (int i = 0; i < len; i++) { Serial.print(data[i], HEX); Serial.print("-"); };
41+
Serial.println("");
42+
//} debug
43+
app.uartRX((uint8_t *)data, len);
4244
}
4345
void callbackDidConnect(void){
4446
app.didConnect();
@@ -49,14 +51,14 @@ void callbackDidDisconnect(void){
4951

5052
void AppInterface::begin(){
5153
ble.sendCommandCheckOK("AT+BAUDRATE=921600");
52-
// LED Activity command is only supported from 0.6.6
54+
// LED Activity command is only supported from 0.6.6: MODE, BLEUART
5355
ble.sendCommandCheckOK("AT+HWMODELED=BLEUART");
5456
ble.sendCommandCheckOK("AT+GAPDEVNAME=Pano Controller");
5557

5658
gatt = new Adafruit_BLEGatt(ble);
5759
service_id = gatt->addService(SERVICE_UUID);
5860
config_char_id = gatt->addCharacteristic(CONFIG_CHAR_UUID, GATT_CHARS_PROPERTIES_READ | GATT_CHARS_PROPERTIES_WRITE | GATT_CHARS_PROPERTIES_WRITE_WO_RESP,
59-
5, 20, BLE_DATATYPE_BYTEARRAY, "Configuration");
61+
3, 20, BLE_DATATYPE_BYTEARRAY, "Configuration");
6062
status_char_id = gatt->addCharacteristic(STATUS_CHAR_UUID, GATT_CHARS_PROPERTIES_READ | GATT_CHARS_PROPERTIES_NOTIFY,
6163
sizeof(PanoState), sizeof(PanoState), BLE_DATATYPE_BYTEARRAY, "Status");
6264
cmd_char_id = gatt->addCharacteristic(CMD_CHAR_UUID, GATT_CHARS_PROPERTIES_WRITE,
@@ -69,7 +71,8 @@ void AppInterface::begin(){
6971
ble.setDisconnectCallback(callbackDidDisconnect);
7072
ble.setBleGattRxCallback(config_char_id, callbackGattRX);
7173
ble.setBleGattRxCallback(cmd_char_id, callbackGattRX);
72-
ble.setBleUartRxCallback(callbackUartRX);
74+
//ble.setBleUartRxCallback(callbackUartRX); // direct polling is faster than ble.update()
75+
ble.setMode(BLUEFRUIT_MODE_DATA);
7376
}
7477

7578
void AppInterface::sendStatus(){
@@ -78,20 +81,15 @@ void AppInterface::sendStatus(){
7881
}
7982

8083
void AppInterface::gattRX(int32_t char_id, uint8_t* data, uint16_t len){
81-
if (char_id == config_char_id || char_id == cmd_char_id){
82-
uartRX(data, len);
83-
}
84+
uartRX(data, len);
8485
}
8586
static bool unpack(settings_t& variable, uint8_t* &data, uint16_t& len){
86-
if (len >= 2*sizeof(variable)){
87-
len -= 2*sizeof(variable);
88-
variable = 0;
89-
for (int i=2*sizeof(variable); i; i--){
90-
variable = (variable <<= 4) + (*data++ - 0x30);
91-
}
87+
if (len >= sizeof(variable)){
88+
len -= sizeof(variable);
89+
memcpy((void*)&variable, data, sizeof(variable));
90+
data += sizeof(variable);
9291
return true;
9392
}
94-
return false;
9593
}
9694
void AppInterface::uartRX(uint8_t* data, uint16_t len){
9795
static uint8_t keyCode;
@@ -123,7 +121,7 @@ void AppInterface::uartRX(uint8_t* data, uint16_t len){
123121
case 0x66: callbacks.goHome(); break;
124122
case 0x67: sendStatus(); break;
125123
case 0x68: // free move
126-
if (len >= 2 * 2 * sizeof(settings_t)){
124+
if (len >= 2 * sizeof(settings_t)){
127125
settings_t horiz_move, vert_move;
128126
unpack(horiz_move, data, len);
129127
unpack(vert_move, data, len);
@@ -161,5 +159,24 @@ bool AppInterface::isConnected(void){
161159
}
162160

163161
void AppInterface::poll(uint32_t timeout){
164-
ble.update(timeout);
162+
static char buffer[UART_BUFFER_SIZE];
163+
static char* eob = buffer + UART_BUFFER_SIZE;
164+
if (!connected || timeout > 0){
165+
ble.update(timeout);
166+
} else {
167+
char* p = buffer;
168+
int c;
169+
do {
170+
do {
171+
// ble.read() can substitute for ble.available() because it can return EOF
172+
c = ble.read();
173+
if (c == EOF) break;
174+
*p++ = (char)c;
175+
} while (p < eob);
176+
177+
if (p != buffer){
178+
callbackUartRX(buffer, p-buffer);
179+
}
180+
} while (p == eob); // we filled the buffer so there may be more to read
181+
}
165182
}

src/app_interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class AppInterface {
4444
void begin(void);
4545
void sendStatus();
4646
bool isConnected();
47-
void poll(uint32_t timeout);
47+
void poll(uint32_t timeout = 0);
4848

4949
void gattRX(int32_t char_id, uint8_t* data, uint16_t len);
5050
void uartRX(uint8_t* data, uint16_t len);

src/pano.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,7 @@ void Pano::startMove(float h, float v){
244244
void Pano::endMove(void){
245245
motors.startBrake();
246246
// TODO: make this async too later ?
247-
while (unsigned long next_event = motors.nextAction()){
248-
microWaitUntil(micros() + next_event);
249-
}
247+
while (motors.nextAction());
250248
}
251249
/*
252250
* Run async operations if needed
@@ -256,12 +254,8 @@ unsigned long Pano::pollEvent(void){
256254
if (micros() > next_event_time){
257255
// for now the only async operation is the motor move
258256
// Pointless at this time because BLE polling takes 4000us and we need 50us spacing.
259-
while (motors.isRunning()){
260-
next_event_time = motors.nextAction();
261-
Serial.println(next_event_time);
262-
if (next_event_time < 25){ // if main loop cannot complete this fast, just wait here
263-
microWaitUntil(micros() + next_event_time);
264-
} else {
257+
while (next_event_time = motors.nextAction()){
258+
if (next_event_time > 500){ // enough time to yield control to main loop
265259
next_event_time = micros() + next_event_time;
266260
break;
267261
}

0 commit comments

Comments
 (0)