I'm trying to code a simple PWM servo control that uses pin 11 on the Arduino Mega 2560. This servo should turn CW (clockwise) or CCW (counterclockwise) depending on pressing and holding one of the two buttons (L and R). The problem I seem to be running into is that the variable I have set to change the OCR1A(i) is incrementing even when the 'if' statements are not true. The buttons work as I've tested using the Serial.println(PINA) to make sure. I'm really not sure where I've gone wrong. I would appreciate any help.
void setup() {
// put your setup code here, to run once:
TCCR1A |= (1<<COM1A1)|(1<<WGM11)|(1<<WGM10);
TCCR1B = 0B00001100; // set mode 7 and prescale to 256
DDRB |= (1<<PB5); // data direction register for PORTB(pwm output pin 11)
DDRA = (1<<2)|(1<<3); // Last 2 digits of PORTA are inputs
Serial.begin(9600); //initialize the serial
}
void loop() {
int i = 63;
// This value controls the duty cycle, duty(%) = OCR1A/255*100
// 63 is just a random start position
OCR1A = i;
int swL;
int swR;
swL = PINA & 0b00000001;
swR = PINA & 0b00000010;
while(i<160) {
if (swR != 0b00000001) {
i++; // increments OCR1A when button R is pressed
Serial.println(PINA); // For testing button is pressed
Serial.println(OCR1A); // debugging use
Serial.println(i); // debugging use
delay(100);
}
if(swL != 0b00000010) {
i--; // negative increments when button L is pressed
Serial.println(PINA);
Serial.println(OCR1A);
Serial.println(i);
delay(100);
}
}
}
It seems like PINA & 0b00000001 provides some value to swL. Now I am not able to find the initial value of PINA but I assume that it is another variable having binary value and so when the two values perform a Bit-wise AND they provide a different value to swL.
I suppose this is the reason why the if condition
if (swL != 0b00000001) evaluates to TRUE and it then enters the if statement.
The same happens to the other variable swR and so it also enters the if statement.
I may be wrong but have a look at the lines:
swL = PINA & 0b00000001;
swR = PINA & 0b00000010;
Thanks, it turns out I just needed an extra set of eyes. My swR and swL were swapped. with a few other changes it now works as intended. Thank you all.
Related
So I'm just getting to grips with node-red and I need to create a conditional global function.
I have two separate global.payloads set to a number value of either 0 or 1.
What I need to happen now is, if global.payload is equal to value 1 then follow this flow, if it is equal to value 0 then follow this one.
I'm just a little confused with the syntax for the function statement. Any help gratefully appreciated.
Since you haven't accepted the current answer, thought I'd give this a try.
I think this is what you need to handle inputs from two separate global contexts. I'm simulating them here with two separate inject nodes to demonstrate:
The checkconf inject node emits a 1 or a 0. Same for the meshstatus node. Substitute your real inputs for those inject nodes. The real work is done inside the function:
var c = context.get('c') || 0; // initialize variables
var m = context.get('m') || 0;
if (msg.topic == "checkconf") // update context based on topic of input
{
c = {payload: msg.payload};
context.set("c", c); // save last value in local context
}
if (msg.topic == 'meshstatus') // same here
{
m = {payload: msg.payload};
context.set('m', m); // save last value in local context
}
// now do the test to see if both inputs are triggered...
if (m.payload == 1) // check last value of meshstatus first
{
if (c.payload == 1) // now check last value of checkconf
return {topic:'value', payload: "YES"};
}
else
return {topic:'value', payload: "NO"};
Be sure to set the "topic" property of whatever you use as inputs so the if statements can discriminate between the two input. Good luck!
You can use the Switch node to do this, rather than a Function node.
When I create a list of button and I addTouchEventListener for it, like below code
for (int i = 0; i < btmPlay.size(); i++ )
{
btmPlay.at(i)->addTouchEventListener([&](Ref *sender, ui::Widget::TouchEventType type){
if (type == ui::Widget::TouchEventType::ENDED)
{
CCLOG("%i", i);
}
});
}
when I touch to the first button, the result is 12 ( btmPlay.size() = 13).
What errors?
In your closure, you're capturing the variable i by reference, and that's why clicking any button will print the same value, in this case 12. If, instead, you capture the variable i by value (by replacing [&] with [=]) then each button will print a different value in the range 0-12.
Btw, capturing i by reference in your example is also wrong, because by the time the closure is invoked, the variable is already out of scope, and printing it is UB.
I'm trying to create a new keyboard somehow, for educational purposes.
I've written this code using actionscript 3.I've created an input text field (named it t1) .when the user presses q button on keyboard(which has an ASCII aquals 81 ) I want the letter b to be printed out on the text field so i've written this code :
stage.addEventListener(KeyboardEvent.KEY_DOWN, pressing);
function pressing(event:KeyboardEvent):void
{
//trace(event.keyCode);
if(event.keyCode==81)
t1.replaceSelectedText("b");
}
the problem was that the method replaceSelectedText prints the tow letters on the screen(q&b) which method can i use instead?
Any help would be appreciated.
When using the replaceSelectedText method, you first need to select the text you want to replace. This can be done with the "setSelection" method. This from the adobe help website:
setSelection(beginIndex:int, endIndex:int):void
"Sets as selected the text designated by the index values of the first and last characters, which are specified with the beginIndex and endIndex parameters."
At the moment, since you don't have any text selected, it appears to just be adding the text "b" as it's replacing nothing. Therefore, you should try first selecting the "q".
Alternatively, you can just use a different method. from the adobe help website:
replaceText(beginIndex:int, endIndex:int, newText:String):void
"Replaces the range of characters that the beginIndex and endIndex parameters specify with the contents of the newText parameter."
This would cut out an extra line of code.
I haven't actually done this myself, so if that doesn't work, here's the link to the adobe help page for Text Fields: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html
I think that to do what you are looking for ( replace a char when it's typed ), a KeyboardEvent.KEY_DOWN is not enough, because when that event is fired, the text is not yet changed, so any change that you did in its handler to your text field will not cancel the insertion of the current typed char. Also, using KeyboardEvent.KEY_UP ( in addition to KeyboardEvent.KEY_DOWN ) will not resolve the problem, because you can fire n times a KeyboardEvent.KEY_DOWN event with the KeyboardEvent.KEY_UP event fired once !
So, I think that the best event that can do the job is the Event.CHANGE event which is fired every time the text of your text field is changed, so you can do like this :
// is there a char to replace ?
var replace_char:Boolean = false;
// the position of the char that we want to replace
var char_position:int = -1;
var text_input:TextField = new TextField();
text_input.type = 'input';
text_input.border = true;
text_input.addEventListener(Event.CHANGE, onTextChange);
function onTextChange(e:Event):void {
if(replace_char && char_position >= 0){
text_input.replaceText(char_position, char_position + 1, 'b');
replace_char = false;
}
}
addChild(text_input);
stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
function _onKeyDown(e:KeyboardEvent):void {
if(e.keyCode == 81) {
replace_char = true;
char_position = text_input.selectionBeginIndex;
}
}
EDIT :
To use a list of keys and their equivalents, you can use an object to stock your keys like this :
// list of all keys (chars) and their equivalents
var chars:Object = {
81: 'b', // q => b
83: 'v', // s => v
68: 'c' // d => c
// other chars
}
var char_to_replace:int = -1;
// other instructions
function onTextChange(e:Event):void {
if(replace_char && char_position >= 0 && char_to_replace >= 0){
// get the equivalent of the pressed key from chars object using : chars[key_pressed]
text_input.replaceText(char_position, char_position + 1, chars[char_to_replace]);
replace_char = false;
}
}
// other instructions
function _onKeyDown(e:KeyboardEvent):void {
if(chars[e.keyCode]) {
replace_char = true;
// save the last pressed key to get its equivalent, or save this last one directly, to replace it next
char_to_replace = e.keyCode;
char_position = text_input.selectionBeginIndex;
}
}
Hope that can help.
Hey everyone so basically what I am trying to accomplish is saving a number with the Shared Object which the the coins that the player collects in the game and if they player quits out of the game and comes back to play again the amount of coins he had when he quit will still show and he will be able to add to that amount if the player picks up more coins. I had this working for a bit but then the textfield started displaying "NAN".
Here is how I have it set up.
The Variable private var nCoins:Number;
In the constructor function I have:
sharedObjectCoins = SharedObject.getLocal("CoinsData");
nCoins = 0 + sharedObjectCoins.data.tCoins;
if (sharedObjectCoins.data.tCoins == null)
{
sharedObjectCoins.data.tCoins = nCoins;
}else
{
trace("Save data found."); // if we did find data...
loadDataTimeAttack(); // ...load the data
}
and in the games Enter.Frame Loop I have the function saveDataCoins which is setup like so:
private function saveDataCoins():void
{
if (nCoins > sharedObjectCoins.data.tCoins )
{
sharedObjectCoins.data.tCoins = nCoins;
}
coinsGraphic.coinsText.text = " " + sharedObjectCoins.data.tCoins;
sharedObjectCoins.flush();
}
not sure if you need the function to where the hitTest takes place between the coins and player but here it is:
private function checkPlayerHitCoins():void
{
for (var i:int = 0; i < aCoinsArray.length; i++)
{
//get current point in i loop
var currentCoins:mcCoin = aCoinsArray[i];
//test if player is hitting current point
if(player.hitTestObject(currentCoins))
{
nCoins += 1;
updatecoinsTextScore();
updateCoinsPauseScreen();
//Add points sound effects
var coinsSEffect:Sound = new coinsSound();
coinsSEffect.play();
//remove point on stage
currentCoins.destroyCoins();
//remove points from array
aCoinsArray.splice(i, 1);
trace("Hit: " + aCoinsArray.length);
}
}
}
Please if anyone could help me with this maybe point something out that I am doing wrong. This code worked perfect one time and when I closed the screen and came back to re test it the textfield displayed NAN and thats it when I hitTest the coins sometimes the NAN switches to a number for like a second but then goes back to NAN.
The first time (or rather every time it creates a new shared object) you will be trying to add undefined to 0, which will result in either a runtime error or NaN.
You need to check if the value exists before attempting to do addition with it.
if(sharedObjectCoints.data && sharedObjectCoins.data.tCoins && !isNaN(sharedObjectCoins.data.tCoins)){
nCoins = Number(sharedObjectCoins.data.tCoins); //there's not point in adding 0
trace("Save data found."); // if we did find data...
loadDataTimeAttack(); // ...load the data
}else{
sharedObjectCoins.data.tCoins = nCoins;
}
Also, if you don't manually set a value to a number var, it will start off life as NaN. eg var nCoins:Number will be NaN until you set it to something.
That said, working with the sharedObject directly like this is a very sloppy way to code your program. Really you should just use shared object to load and save the value, and everything in between use a strongly typed variable.
var nCoins:int = 0;
var tCoins:int = 0;
sharedObjectCoins = SharedObject.getLocal("CoinsData");
if(sharedObjectCoins.data && sharedObjectCoins.data.tCoins && !isNaN(sharedObjectCoins.data.tCoins){
tCoins = int(sharedObjectCoins.data.tCoins);
}else{
//no shared object, use default value for tCoins
tCoins = 0; //or whatever it should start off as.
}
Then write a save function
private function saveSharedObject():void {
sharedObjectCoins.data.tCoins = tCoins;
sharedObjectCoins.flush();
}
Then replace all other instances of sharedObjectCoins.data.tCoins with the var tCoins
It's probably best not to flush the shared object every frame for performance purposes.
Also, shared objects may or may not actually save, depending on user preferences, storage space available, etc. They should not be relied upon for critical data retention.
You can listen for problems with the shared object with AsyncErrorEvent.ASYNC_ERROR I believe (It's been a while since I've worked with AS3 Shared Objects)
I'm making a dots and boxes game in flash using actionscript 3.
Currently I'm completely stuck as I want the player to click two buttons before a line is displayed. I planned to do something like this using the if statement
if button1 and button2 clicked
line1 visible = true
I've also tried adding eventlisteners with one function
function showLine(e:Event):void {
blue0001.visible = true
}
dot00.addEventListener(MouseEvent.CLICK, showLine);
But as far as I know this can only be used when you want to click one button. Is there anyway to have two eventlisteners satisfyed before the function is carried out?
Also how would I (if i can) use the if statements to carry out this?
You would probably do something like this, pseudo-code:
Assume all of the dots are in a dots array.
for (var i: Number = 0; i < dots.length; i++) {
dots.addEventListener(MouseEvent.CLICK, dotClicked, false, 0, true);
}
dotSelected = null;
function dotClicked(evt:MouseEvent):void {
if (dotSelected && isNeighbor(evt.target, dotSelected)) {
showLineConnecting(evt.target, dotSelected)
dotSelected = null;
} else if (!dotSelected) {
highlightDot(evt.target);
dotSelected = evt.target;
} else {
showError("You must click an adjacent dot");
}
}
At the request of the OP, this is what's going on.
for (var i: Number = 0; i < dots.length; i++) {
dots.addEventListener(MouseEvent.CLICK, dotClicked, false, 0, true);
}
Add an event listener to every dot. Here I am assuming you already have an array of dots defined. Each instance in the Array would be a MovieClip (likely), Sprite, or another DisplayObject.
dotSelected = null;
We will use a variable to keep track of any currently selected dot. Since no dot will be selected when the game starts, we set it to null.
function dotClicked(evt:MouseEvent):void {
if (dotSelected && isNeighbor(evt.target, dotSelected)) {
showLineConnecting(evt.target, dotSelected)
dotSelected = null;
} else if (!dotSelected) {
highlightDot(evt.target);
dotSelected = evt.target;
} else {
showError("You must click an adjacent dot");
}
}
This is the function that will get called when any dot is clicked. For explanation's sake, let's take the first click of the game. dotSelected is null, so the first if is false. The second if though is true, because (!dotSelected) is true. So, we run some function I called highlightDot with the dot as the argument. That function could look something like this:
function hightlightDot(dot:Dot):void {
dot.gotoAndStop("selected");
}
Now a second click is made. Now the first part of the first if, dotSelected, is true. The second part is now evaluated. Again I put in a made up function isNeighbor. The isNeighbor function takes two arguments, the dot that was just clicked and the dot that has already been clicked. This function needs to make sure the two dots are adjacent. This could be something like...
function isNeighbor(dot1:Dot, dot2:Dot):void {
return ((dot1.xGrid == dot2.xGrid && Math.abs(dot1.yGrid - dot2.yGrid) == 1) || (Math.abs(dot1.xGrid - dot2.xGrid) == 1) && dot1.yGrid == dot2.yGrid));
}
The above function assumes that the instances of Dot have some properties xGrid and yGrid which defines where in the playing board they sit. If they are in the same row and 1 column apart they are neighbors. If they are in the same column and 1 row apart they are neighbors.
The last thing that happens in a function showLineConnecting is called. That function will again take the two adjacent dots as arguments. It will then draw a line between them in whatever way you choose to do that. Finally, dotSelected is set back to null, allowing another set of dots to be selected.
One thing I just realized, it would probably be helpful to have an additional property that gets triggered on a Dot when it is connected to all of its neighbors so it could no longer be selected.
You will also need logic to handle knowing that a box has been created. For that you would likely just iterate the possibilities given the line that was just drawn. For each line drawn there are only two possible boxes that have been created. So check them both. Watch out for edges.