Arduino sketch that reads serial characters as a command and does something - ios5

Currently I am trying to get a sketch working where the Arduino will read a series of characters as a command, and do something based on the series of characters sent from an iDevice. I am using an iPhone 3GS that is jailbroken to send characters to the Arduino. The method that sends the serial characters looks like the following,
- (IBAction)blinkFlow_A_LED:(id)sender {
// Method to blink the Flow_A LED on the kegboard-mini Arduino shield (<https://github.com/Kegbot/kegboard>).
NSLog(#"blink Flow_A btn pressed");
// Open serial port / interface
[serial open:B2400];
NSLog(#"%c", [serial isOpened]);
// Send serial data (TX)
char buffer [7];
buffer[0] = '{';
buffer[1] = 'b';
buffer[2] = 'l';
buffer[3] = 'i';
buffer[4] = 'n';
buffer[5] = 'k';
buffer[6] = '}';
[serial write:buffer length:7];
}
I have created a simple sketch that blinks the LED on the shield I am using, but I want the LED to blink conditionally when the button is clicked in the iOS app. The sketch that blinks the LED looks like the following,
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
This sketch is specific to making the kegboard-mini shield.
http://arduino.cc/forum/index.php?topic=157625.new;topicseen#new
This example code is in the public domain.
*/
// Pin D4 - should be connected to the flow_A LED
// Give it a name
int led = 4;
// The setup routine runs once when you press reset:
void setup() {
// Initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// The loop routine run over and over again forever:
void loop() {
digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level)
delay(1000); // Wait for one second
digitalWrite(led, LOW); // Turn the LED off by making the voltage LOW
delay(1000); // Wait for a second
}

That is a simple sketch!
You may want to begin with looking at the Arduino reference page: Serial
In setup(), you need at least Serial.begin(2400);.
Now, I'll suggest that reading and decoding the string "{blink}" seems like overkill. Let me suggest you send one character (for example 'b'), and detect one character, at least to start. Check out .available() and .read() on the Serial reference page. With these you can determine if a character has arrived at the Arduino and read in a single character.
You can then use these if you want to build a string of characters one at a time and compare it to String("{blink}"). This is a bit more complicated, especially if you take into account exceptions (like lost or damaged characters).
You can easily test your program using the Serial monitor tool -- just be advised that you have to hit "send" to make the characters go out.

I ended putting a simple sketch together like this which allows me to store an array of serial bytes into a String thanks to the SerialEvent example.
The sketch I am currently working with looks like the following,
/*
* kegboard-serial-simple-blink07
* This code is public domain
*
* This sketch sends a receives a multibyte String from the iPhone
* and performs functions on it.
*
* Examples:
* http://arduino.cc/en/Tutorial/SerialEvent
* http://arduino.cc/en/Serial/read
*/
// Global variables should be identified with "_"
// flow_A LED
int led = 4;
// relay_A
const int RELAY_A = A0;
// Variables from the sketch example
String inputString = ""; // A string to hold incoming data
boolean stringComplete = false; // Whether the string is complete
void setup() {
Serial.begin(2400); // Open a serial port. Sets data rate to 2400 bit/s
Serial.println("Power on test");
inputString.reserve(200);
pinMode(RELAY_A, OUTPUT);
}
void open_valve() {
digitalWrite(RELAY_A, HIGH); // Turn RELAY_A on
}
void close_valve() {
digitalWrite(RELAY_A, LOW); // Turn RELAY_A off
}
void flow_A_blink() {
digitalWrite(led, HIGH); // Turn the LED on (HIGH is the voltage level)
delay(1000); // Wait for one second
digitalWrite(led, LOW); // Turn the LED off by making the voltage LOW
delay(1000); // Wait for a second
}
void flow_A_blink_stop() {
digitalWrite(led, LOW);
}
void loop() {
// Print the string when newline arrives:
if (stringComplete) {
Serial.println(inputString);
// Clear the string:
inputString = "";
stringComplete = false;
}
if (inputString == "{blink_Flow_A}") {
flow_A_blink();
}
}
// SerialEvent occurs whenever a new data comes in the
// hardware serial RX. This routine is run between each
// time loop() runs, so using delay inside loop can delay
// response. Multiple bytes of data may be available.
void serialEvent() {
while(Serial.available()) {
// Get the new byte:
char inChar = (char)Serial.read();
// Add it to the inputString:
inputString += inChar;
// If the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}

Related

PlatformIO in VSCode

I downloaded the latest version of VS Code with PlatformIO, i also downloaded the library Mouse.h from PlatformIO Library Manager, and even so, after i upload the code to my Micro Pro the mouse does not respond to the joystick!
But the same code works when i upload via Arduino IDE!
I compared the Mouse.h from .platformio/lib with the Mouse.h from program files\Arduino\libraries
I compared the Mouse.cpp from .platformio/lib with the Mouse.cpp from program files\Arduino\libraries
And they have exactly the same code!
This is my code for my MICRO PRO 32u4 5v:
/* HID Joystick Mouse Example
by: Jim Lindblom
date: 1/12/2012
license: MIT License - Feel free to use this code for any purpose.
No restrictions. Just keep this license if you go on to use this
code in your future endeavors! Reuse and share.
This is very simplistic code that allows you to turn the
SparkFun Thumb Joystick (http://www.sparkfun.com/products/9032)
into an HID Mouse. The select button on the joystick is set up
as the mouse left click.
*/
#include <Arduino.h>
#include <Mouse.h>
int horzPin = A0; // Analog output of horizontal joystick pin
int vertPin = A1; // Analog output of vertical joystick pin
int selPin = 9; // select button pin of joystick
int vertZero, horzZero; // Stores the initial value of each axis, usually around 512
int vertValue, horzValue; // Stores current analog output of each axis
const int sensitivity = 200; // Higher sensitivity value = slower mouse, should be <= about 500
int mouseClickFlag = 0;
void setup()
{
pinMode(horzPin, INPUT); // Set both analog pins as inputs
pinMode(vertPin, INPUT);
pinMode(selPin, INPUT); // set button select pin as input
digitalWrite(selPin, HIGH); // Pull button select pin high
delay(1000); // short delay to let outputs settle
vertZero = analogRead(vertPin); // get the initial values
horzZero = analogRead(horzPin); // Joystick should be in neutral position when reading these
}
void loop()
{
vertValue = analogRead(vertPin) - vertZero; // read vertical offset
horzValue = analogRead(horzPin) - horzZero; // read horizontal offset
//delay(3000);
if (vertValue != 0)
Mouse.move(0, vertValue/sensitivity, 0); // move mouse on y axis
if (horzValue != 0)
Mouse.move((horzValue/sensitivity) *-1, 0, 0); // move mouse on x axis
if ((digitalRead(selPin) == 0) && (!mouseClickFlag)) // if the joystick button is pressed
{
mouseClickFlag = 1;
Mouse.press(MOUSE_LEFT); // click the left button down
}
else if ((digitalRead(selPin))&&(mouseClickFlag)) // if the joystick button is not pressed
{
mouseClickFlag = 0;
Mouse.release(MOUSE_LEFT); // release the left button
}
}
Did you restart VS Code after installing the lib?
For me it fix this kind of problems in some cases.
Edit: Did you "rebuild IntelliSense Index" by press "Ctrl + shift + p"?

STM32F4 Discovery

I have STM32F4 Discovery. I use IAR embedded Workbench. I am new to this kit. I want to measure distance. my code does not give an error. the distance is always zero. What could be the error? please help me . thanks everyone
#include "stm32f4_discovery.h"
#include "delay.h"
uint32_t Read_Distance(void);
void Init();
uint32_t distance ;
int main()
{
Init(); // initialisation de pin
SysTick_Init(); // pour pouvoire utiliser la fonction delay :)
while (1)
{
distance=Read_Distance();
delay_nms(100);
}
}
void Init()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitTypeDef gpioStructure;
gpioStructure.GPIO_Pin = GPIO_Pin_10;
gpioStructure.GPIO_Mode = GPIO_Mode_OUT;
gpioStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &gpioStructure);
gpioStructure.GPIO_Pin = GPIO_Pin_11;
gpioStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init(GPIOD, &gpioStructure);
}
//Les Pins pour le Test sont PD10 (Trig) et PD11(echo)
uint32_t Read_Distance(void)
{
__IO uint8_t flag=0;
__IO uint32_t disTime=0;
GPIO_SetBits(GPIOD,GPIO_Pin_10);
delay_nus(10);
GPIO_ResetBits(GPIOD,GPIO_Pin_10);
while(flag == 0)
{
while(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == SET)
{
disTime++;
flag = 1;
}
}
return disTime;
}
Looks like you're using one of those ultrasonic distance measurement modules
Try this:
while(flag == 0)
{
disTime++;
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == SET)
{
flag = 1;
}
}
You should use one of the hardware timers to get a more accurate time measurement.
Now I've had time to think more about it I remember now that you get a pulse sent back with a width proportional to the distance. I think this is the correct answer:
// Wait for pulse to start
while (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == RESET)
{
NOP;
}
// Measure pulse width
while(flag == 0)
{
disTime++;
// Has pulse ended
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == RESET)
{
flag = 1;
}
}
You may also want to tackle the case where the pulse is never received because this could will block forever.
If I understand correctly, D10 is wired to D11 and you want to check how long your signal remains high. If this is the case, you should increment a counter in timer interrupt handler when your pin is high and reset that counter variable once you've read it.

arduino not writing to sd card

I have an Arduino with a Seeedstudio sd card shield v4.0 with a prototpye shield above that, and on that is a TMP36 temperature sensor and a red and two green LEDs, the red to show that it is "Ready" to log data, the first green to show that it is currently "logging data" and the last LED to show that the data was "Saved" to the SD card, which it dosent, at the beggining of the file, however, it creates the line "Testing 1, 2, 3..." in a txt file called TEST. in that same file there should be the data, but there is no data, it will write to the card in setup, but not in loop. Can anyone help me?
Code:
#include <toneAC.h>
#include <SPI.h>
#include <SD.h>
int readyLED = 2;
int startLED = 8;
int buzzer = 7;
int tempSensor = A0;
int readyButton = 5;
int sampleNo = 0;
int button_mode = 1;
int saveLED = 4;
File myFile;
void setup() {
// put your setup code here, to run once:
pinMode(readyLED, OUTPUT);
digitalWrite(readyLED, HIGH);
pinMode(saveLED, OUTPUT);
digitalWrite(saveLED, LOW);
pinMode(startLED, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(10, OUTPUT);
pinMode(tempSensor, INPUT);
pinMode(readyButton, INPUT);
digitalWrite(readyLED, HIGH);
digitalWrite(startLED, LOW);
Serial.begin(9600);
while (!Serial){}
Serial.println("Initializing SD card...");
if(!SD.begin(4)){
Serial.println("Failed!");
return;
}
Serial.println("Success!");
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) {
Serial.println("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
delay(500);
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(readyLED, HIGH);
digitalWrite(startLED, LOW);
delay(700);
digitalWrite(startLED, HIGH);
delay(650);
int reading = analogRead(tempSensor);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureC = (voltage - 0.5) * 100;
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
Serial.print("Sample No. ");
sampleNo = sampleNo + 1;
Serial.print(sampleNo);
Serial.print(" Temperature: ");
Serial.print(temperatureF);
Serial.println(" F");
myFile = SD.open("test.txt", FILE_WRITE);
if(myFile){
Serial.println("Test.txt");
}
while(myFile.available()){
myFile.print("Sample No. ");
myFile.print(sampleNo);
myFile.print(" Temperature: ");
myFile.print(temperatureF);
myFile.println(" F");
}
delay(30);
digitalWrite(saveLED, HIGH);
delay(10);
digitalWrite(saveLED, LOW);
delay(10);
myFile.close();
}
You may want to check to make sure your while loop is actually being run. Since you know you can write to the SD card from void setup() you know your code inside the while loop works, but is the while loop actually being run, or is it evaluating to false and being skipped?
Have you considered the time it takes to write down data as an issue? You may be asking for it write down data before the Arduino code has time to process.

mbed not sleep with RTOS

I want to create a low power application with mbed (LPC1768) and have been following tutorial by Jim Hamblen at: https://mbed.org/cookbook/Power-Management and also http://mbed.org/users/no2chem/notebook/mbed-power-controlconsumption/
I was able to wake the mbed from Sleep() by GPIO interrupt, UART interrupt, and Ticker. I use PowerControl library.
Here is my code:
#include "mbed.h"
#include "PowerControl/PowerControl.h"
#include "PowerControl/EthernetPowerControl.h"
// Need PowerControl *.h files from this URL
// http://mbed.org/users/no2chem/notebook/mbed-power-controlconsumption/
// Function to power down magic USB interface chip with new firmware
#define USR_POWERDOWN (0x104)
int semihost_powerdown() {
uint32_t arg;
return __semihost(USR_POWERDOWN, &arg);
}
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
bool rx_uart_irq = false;
Serial device(p28, p27); // tx, rx
InterruptIn button(p5);
// Circular buffers for serial TX and RX data - used by interrupt routines
const int buffer_size = 255;
// might need to increase buffer size for high baud rates
char tx_buffer[buffer_size];
char rx_buffer[buffer_size];
// Circular buffer pointers
// volatile makes read-modify-write atomic
volatile int tx_in=0;
volatile int tx_out=0;
volatile int rx_in=0;
volatile int rx_out=0;
// Line buffers for sprintf and sscanf
char tx_line[80];
char rx_line[80];
void Rx_interrupt();
void blink() {
myled2 = !myled2;
}
int main() {
//int result;
device.baud(9600);
device.attach(&Rx_interrupt, Serial::RxIrq);
// Normal mbed power level for this setup is around 690mW
// assuming 5V used on Vin pin
// If you don't need networking...
// Power down Ethernet interface - saves around 175mW
// Also need to unplug network cable - just a cable sucks power
PHY_PowerDown();
myled2 = 0;
// If you don't need the PC host USB interface....
// Power down magic USB interface chip - saves around 150mW
// Needs new firmware (URL below) and USB cable not connected
// http://mbed.org/users/simon/notebook/interface-powerdown/
// Supply power to mbed using Vin pin
//result = semihost_powerdown();
// Power consumption is now around half
// Turn off clock enables on unused I/O Peripherals (UARTs, Timers, PWM, SPI, CAN, I2C, A/D...)
// To save just a tiny bit more power - most are already off by default in this short code example
// See PowerControl.h for I/O device bit assignments
// Don't turn off GPIO - it is needed to blink the LEDs
Peripheral_PowerDown( ~( LPC1768_PCONP_PCUART0 |
LPC1768_PCONP_PCUART2 |
0));
// use Ticker interrupt and Sleep instead of a wait for time delay - saves up to 70mW
// Sleep halts and waits for an interrupt instead of executing instructions
// power is saved by not constantly fetching and decoding instructions
// Exact power level reduction depends on the amount of time spent in Sleep mode
//blinker.attach(&blink, 0.05);
//button.rise(&blink);
while (1) {
myled1 = 0;
printf("bye\n");
Sleep();
if(rx_uart_irq == true) {
printf("wake from uart irq\n");
}
myled1 = 1;
}
}
// Interupt Routine to read in data from serial port
void Rx_interrupt() {
myled2 = !myled2;
rx_uart_irq = true;
uint32_t IRR0= LPC_UART2->IIR;
while ((device.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
rx_buffer[rx_in] = LPC_UART2->RBR;
rx_in = (rx_in + 1) % buffer_size;
}
}
Here is the problem: The Sleep() doesn't put the mbed to sleep when mbed-rtos library is added. Even when I don't use any function calls from the rtos library , Sleep() doesn't work.
My explanation: Probably the rtos has a timer running in the background and it generates an interrupt every now and then. (But it kinda doesn't make sense because I haven't use any function or object from rtos library)
My question:
Has any one made the Sleep() function work with rtos? if yes, please point me to the right direction or if you have the solution, please share.
I'm not sure if the Sleep() function is designed for RTOS use, but I doubt it. Someone with better knowledge in mbed-rtos could probably tell for sure, but I suspect that IRQ handling in the RTOS could cause the problem. If Sleep() relies on WFE then the MCU will sleep if there is no pending interrupt flag. In a super loop design you (should) have full control over this; with an RTOS you don't.
I suggest using Thread::wait() instead, which should have full knowledge about what the RTOS does. Can't tell if it causes a sleep, but I expect no less.
I used the following library once and it worked flawlessly. I am not sure if it would work with mbed 5 but its worth a try.
https://os.mbed.com/users/no2chem/code/PowerControl/

bufferuntil('\n) won’t trigger serialevent processing with Eclipse

I want to do the simplest thing to plot a graph from the serial port of Arduino with the Processing software. I use Eclipse.
I did as the tutorials say about the plugins. I also copied the code from the Arduino site which is this:
import processing.serial.*;
Serial myPort; // The serial port
int xPos = 1; // Horizontal position of the graph
void setup () {
// Set the window size:
size(400, 300);
// List all the available serial ports
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my Arduino, so I open Serial.list()[0].
// Open whatever port is the one you're using.
myPort = new Serial(this, Serial.list()[0], 9600);
// Don't generate a serialEvent() unless you get a newline character:
myPort.bufferUntil('\n');
// Set the initial background:
background(0);
}
void draw () {
// Everything happens in the serialEvent()
}
void serialEvent (Serial myPort) {
// Get the ASCII string:
String inString = myPort.readStringUntil('\n');
if (inString != null) {
// Trim off any whitespace:
inString = trim(inString);
// Convert to an int and map to the screen height:
float inByte = float(inString);
inByte = map(inByte, 0, 1023, 0, height);
// Draw the line:
stroke(127, 34, 255);
line(xPos, height, xPos, height - inByte);
// At the edge of the screen, go back to the beginning:
if (xPos >= width) {
xPos = 0;
background(0);
}
else {
// Increment the horizontal position:
xPos++;
}
}
}
There is a problem that the bufferUntil('\n') does not trigger the serialevent.
I know that there was a bug. In case you try to set an 8-bit int to a 32-bit int, it goes to hell.
The Processing IDE works great though. Eclipse does not trigger at all. Is there a solution?
Note that bufferUntil('\n') takes an integer value. You're giving it a char. At the very least try bufferUntil(10) just to see if there's some oddness going on there, but it might be worth simply printing the values see coming in on myPort and see what comes by when you send a newline.